Classes are a central concept in object-oriented programming. In Crystal, everything is an object, every object has a type, and it can respond to some methods. Classes are blueprints to create objects, providing initial values for state, like variables, and implementations of behavior, like methods. Objects are class instances that hold all the instance variables and states.
A class is defined using the class
keyword, followed by the name of the class written in UpperCamelCase
.
class Account
end
To create an instance of a class, call the class name using the new
method.
class Account
end
account = Account.new
In the example above the variable account
is an instance of the class Account
.
When creating an instance, a special method called initialize
acts as a constructor.
It is called when an instance is created.
The constructor allows you to set the initial state of the instance.
The initialize
method can take arguments, which are passed when creating an instance.
class Account
def initialize(number)
5 + number # => 9
end
end
Account.new(4)
The initialize
method cannot manually return a value, instead, new
returns the newly created instance.
class Account
def initialize(number)
5 + number
end
end
Account.new(4)
# => #<Account:0x7f5dc33dcea0>
An instance method is a method that is available to an instance of a class, and can be called on that instance.
Instance methods are defined using the def
keyword, followed by the method's name.
They are defined inside the class definition.
class Account
def balance
100
end
end
account = Account.new
account.balance # => 100
Instance variables are variables that are available in all methods of the instance.
To access an instance variable you need to define an instance method.
They can be initialized in the initialize
method.
They are defined using the @
prefix.
class Account
def initialize
@balance = 100
end
def balance
@balance
end
end
account = Account.new
account.balance
# => 100
Instance variables may also be defined inside the class definition.
class Account
@age = 0
end
Instance variables can be initialized with an argument passed to the initialize
method.
Since Crystal can't infer the type of argument used during initialization, it must be specified.
If you want to read more about this, you can read: type-inference.
To specify the type of the variable you can use the :
symbol, followed by the type.
For example, if you want to create an instance variable called balance
of type Int32
, you can do the following: @balance : Int32
.
Or if you want to create an instance variable called raining
of type Bool
, you can do the following: @raining : Bool
.
There are a few ways to implement this, either by in the initialize
method declaring the argument with the type, and then assigning the instance variable to the argument, like the following example:
class Account
def initialize(balance : Int32)
@balance = balance
end
def balance
@balance
end
end
account = Account.new(1)
account_2 = Account.new(5)
account.balance
# => 1
account_2.balance
# => 5
Another way is to declare the instance variable type in the class definition in the form: @<variable> : <Type>
, like the following example:
class Weather
@raining : Bool
def initialize(raining)
@raining = raining
end
def raining
@raining
end
end
weather = Weather.new(true)
weather.raining
# => true
There is a shorthand for initializing instance variables in the arguments of the initialize
method, using the same syntax @<variable> : <Type>
.
This combines the assignment of the instance variable to the argument and the declaration of the instance variable type.
class Account
def initialize(@balance : Int32)
end
end
Methods can modify instance variables. These methods can be called on the instance of the class. When a method modifies an instance variable, that change is only available in the instance of the class you called it on.
class Account
def initialize(balance : Int32)
@balance = balance
end
def withdraw(amount)
@balance -= amount
end
def balance
@balance
end
end
account = Account.new(10)
account_2 = Account.new(10)
account.balance
# => 10
account_2.balance
# => 10
account.withdraw(5)
account.balance
# => 5
account_2.balance
# => 10
Class methods are methods that are defined for a class but not for its instances.
They offer a way to create methods not dependent on the instance's state.
They are defined using the def
keyword, followed by self.<method name>
.
self
is a reference to the namespace which self is being called from.
In this case, it refers to the class, Account
.
It would be the same as if you would have written Account.
, but self.
is the preferred way.
class Account
def self.balance
100
end
end
Account.balance
# => 100