When you don't assign a variable in the inner constructor, how does it get assigned

Consider the following code:

struct Employee
    ID::Int32
    name::String
end

and I can create an object and call any field:

svetlana = Employee(1,"Queen Svetlana")
println(svetlana.name)

If I require validation, I can have an inner constructor:

struct Employee
    ID::Int32
    name::String

    function Employee(ID::Int32,name::String)
        if ID < 0
            error("ID is invalid!")
        end

        if isempty(name)
            error("Employee name cannot be blank!")
        end

        ID = ID
        name = name

        new(ID,name)
    end
end

When I remove the variable assignment in the constructor, how do the fields get assigned? I can still call ID or name and get the value:

struct Employee
    ID::Int32
    name::String

    function Employee(ID::Int32,name::String)
        if ID < 0
            error("ID is invalid!")
        end

        if isempty(name)
            error("Employee name cannot be blank!")
        end
        new(ID,name)
    end
end

The ID and name in this case are the ones I passed into the constructor, and once they’re validated I return them.

svetlana = Employee(1,"Queen Svetlana")
println(svetlana.name)

Why does calling svetlana.name and get the value?

1 Like

Not sure I understand the question fully, but the ID and name fields do not get set on the struct by the assignments, but by the new(ID, name) call whose result (an Employee) you subsequently return from the constructor. Hence, the assignments are not useful (certainly not in the form ID=ID as you used).

2 Likes

In the internal constructor method, ID and name are just parameters.
The special function new() creates an object with these parameters, therefore, they do not necessarily have to have the same name as the structure’s attributes. Ex:

struct Employee
    ID::Int32
    name::String

    function Employee(id::Int32, n::String)
        if id < 0
            error("ID is invalid!")
        end

        if isempty(n)
            error("Employee name cannot be blank!")
        end

        new(id, n)
    end
end

PS: Sorry for my english.

3 Likes

To complement the other answers, the fields are filled in the order they are defined in the struct, by the arguments to new. Since ID is the first field in the struct it gets the value from the first argument to new, and so on.

4 Likes

In the documentation, the inner constructor does have assignments (it does some calculations before it does the assignment).

To clarify, when I remove the assignments, how does ID and name still get its values assigned? I always assumed constructors were supposed to assign the values.

In the example you refer to the values of num and den are recalculated, based on the value of g. That is why those assignments are there. But the values are set on the struct by the new(num, den) call.

No, it really is the new() call that assigns the values. You might be familiar with C++ for setting fields in constructors, but in Julia it works differently. You could just as easily have used new(3, 4) to set the num and den values of the struct. In fact, the return value of the constructor is actually what is used:

julia> struct Employee
           ID::Int32
           name::String
           function Employee(ID::Int, name::String)
               return 1.23
           end
       end

julia> e = Employee(9, "abc")
1.23

julia> typeof(e)
Float64
2 Likes

If I wanted to do some work on the string, like strip it to remove white space and call title(), then would the assignments make sense?

function Employee(ID::Int32, name::String)
    if isempty(strip(name))
        error("Employee name cannot be blank!")
    end
    name = title(name)
    new(ID,name)
end

You could either assign the updated value to name and then pass that to new() or call new(ID, title(name)) directly, it has the same end result.

2 Likes