I am teaching myself Crystal-lang and I came across a section in the documentation that I don't quite understand.
Here is the documetation page.
On that page it gives the following code:
class Person
@age = 0
def initialize(@name : String)
end
end
This is followed by the following statement:
This will initialize @age to zero in every constructor. This is useful to avoid duplication, but also to avoid the Nil type when reopening a class and adding instance variables to it.
Can someone please explain, or show me an example of the bolded behaviour? I'm not certain I understand what it means by "reopening a class and adding an instance variable to it".
Here is an example of reopening a class, and adding an instance variable to it:
class Person
@age = 0
def initialize(@name : String)
end
end
# Usually in another file
class Person
def gender=(gender : String)
@gender = gender
end
def gender
@gender
end
end
person = Person.new("RX14")
typeof(person.gender) # => String | Nil
person.gender # => nil
person.gender = "???"
person.gender # => "???"
We add the @gender
instance variable, which is not initialized in the def initialize
. The compiler infers the type of @gender
to be String | Nil
, since it is assigned to a string in gender=
, but it is not initialized in the constructor, meaning it can also be nil
.
However, we can add a default value to the @gender
instance variable, which applies to all constructors, define before or after the default:
class Person
@age = 0
def initialize(@name : String)
end
end
# Usually in another file
class Person
@gender = "unknown"
def gender=(gender : String)
@gender = gender
end
def gender
@gender
end
end
person = Person.new("RX14")
typeof(person.gender) # => String
person.gender # => "unknown"
person.gender = "???"
person.gender # => "???"
This avoids the @gender
variable getting the String | Nil
type, since it is initialized to "unknown"
when Person
is constructed. Since Nil
types are often avoided, this is an important tool to have.