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:

    1. class Person
    2. def initialize(@name : String)
    3. end
    4. end
    5. class Employee < Person
    6. def initialize(@name : String, @company_name : String)
    7. end
    8. end
    9. Employee.new "John", "Acme" # OK
    10. Employee.new "Peter" # Error: wrong number of arguments for 'Employee:Class#new' (1 for 2)

    You can override methods in a derived class:

    1. class Person
    2. def greet(msg)
    3. end
    4. class Employee < Person
    5. def greet(msg : Int32)
    6. puts "Hi, this is a number: #{msg}"
    7. end
    8. end
    9. e = Employee.new
    10. e.greet "everyone" # "Hi, everyone"
    11. 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

    1. class Foo
    2. end
    3. end
    4. foo_arr = [Bar.new] of Foo # => [#<Bar:0x10215bfe0>] : Array(Foo)
    5. 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 Bars 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).

    1. class Foo
    2. end
    3. class Bar < Foo
    4. end
    5. class Test
    6. @arr : Array(Foo)
    7. def initialize
    8. @arr = [Bar.new] of Foo
    9. end