Methods and instance variables

We can simplify our constructor by using a shorter syntax for assigning a method parameter to an instance variable:

class Person
  def initialize(@name : String)
    @age = 0
  end

  def age
    @age
  end
end

Right now, we can't do much with a person aside from create it with a name. Its age will always be zero. So lets add a method that makes a person become older:

class Person
  def initialize(@name : String)
    @age = 0
  end

  def age
    @age
  end

  def become_older
    @age += 1
  end
end

john = Person.new "John"
peter = Person.new "Peter"

john.age # => 0

john.become_older
john.age # => 1

peter.age # => 0

Method names begin with a lowercase letter and, as a convention, only use lowercase letters, underscores and numbers.

Getters and setters

The Crystal Standard Library provides macros which simplify the definition of getter and setter methods:

class Person
  property age
  getter name : String

  def initialize(@name)
    @age = 0
  end
end

john = Person.new "John"
john.age = 32
john.age # => 32

For more information on getter and setter macros, see the standard library documentation for Object#getter, Object#setter, and Object#property.

As a side note, we can define become_older inside the original Person definition, or in a separate definition: Crystal combines all definitions into a single class. The following works just fine:

class Person
  def initialize(@name : String)
    @age = 0
  end
end

class Person
  def become_older
    @age += 1
  end
end

Redefining methods, and previous_def

If you redefine a method, the last definition will take precedence.

class Person
  def become_older
    @age += 1
  end
end

class Person
  def become_older
    @age += 2
  end
end

person = Person.new "John"
person.become_older
person.age # => 2

You can invoke the previously redefined method with previous_def:

class Person
  def become_older
    @age += 1
  end
end

class Person
  def become_older
    previous_def
    @age += 2
  end
end

person = Person.new "John"
person.become_older
person.age # => 3

Without arguments or parentheses, previous_def receives all of the method's parameters as arguments. Otherwise, it receives the arguments you pass to it.

Catch-all initialization

Instance variables can also be initialized outside initialize methods:

class Person
  @age = 0

  def initialize(@name : String)
  end
end

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.

To the extent possible under law, the persons who contributed to this workhave waived
all copyright and related or neighboring rights to this workby associating CC0 with it.
https://crystal-lang.org/reference/syntax_and_semantics/methods_and_instance_variables.html