Inheritance
A class inherits all instance variables and all instance and class methods of a superclass, including its constructors (new
and initialize
).
If a class defines a new
or initialize
then its superclass constructors are not inherited:
class Person
def initialize(@name : String)
end
end
class Employee < Person
def initialize(@name : String, @company_name : String)
end
end
Employee.new "John", "Acme" # OK
Employee.new "Peter" # Error: wrong number of arguments for 'Employee:Class#new' (1 for 2)
You can override methods in a derived class:
class Person
def greet(msg)
end
class Employee < Person
def greet(msg : Int32)
puts "Hi, this is a number: #{msg}"
end
end
e = Employee.new
e.greet "everyone" # "Hi, everyone"
e.greet 1 # "Hi, this is a number: 1"
You can invoke a superclass’ method using super
:
Without arguments or parentheses, super
receives all of the method’s parameters as arguments. Otherwise, it receives the arguments you pass to it.
Covariance and Contravariance
One place inheritance can get a little tricky is with arrays. We have to be careful when declaring an array of objects where inheritance is used. For example, consider the following
class Foo
end
end
foo_arr = [Bar.new] of Foo # => [#<Bar:0x10215bfe0>] : Array(Foo)
bar_arr2 = [Foo.new] of Bar # compiler error
One place this might trip you up is when automatic casting comes into play. For example, the following won’t work:
we’ve declared @arr
as type Array(Foo)
so we may be tempted to think that we can start putting Bar
s in there. Not quite. In the initialize
, the type of the [Bar.new]
expression is Array(Bar)
, period. And Array(Bar)
is not assignable to an Array(Foo)
instance var.
What’s the right way to do this? Change the expression so that it is of the right type: Array(Foo)
(see example above).
class Foo
end
class Bar < Foo
end
class Test
@arr : Array(Foo)
def initialize
@arr = [Bar.new] of Foo
end