milanbalazs
milanbalazs

Reputation: 5329

Crystal - Pass instance variable to parent class

I have a Crystal code with inheritance.

Here is a working code which doesn't contains the inheritance:

class Person
  def initialize(@person_name : String)
  end
  def greet_person()
    puts "Hi, #{@person_name} person"
  end
  def something()
    puts "It is something"
  end
end

class Employee
  def initialize(@name : String, @company_name : String)
  end
  def greet_employee()
    puts "Hi, #{@name} in #{@company_name} company"
  end
end

bob = Person.new "Bob"
bob.greet_person
bob.something

john = Employee.new "John", "Acme"
john.greet_employee

Output:

Hi, Bob person
It is something
Hi, John in Acme company

If I implement the inheritance:

class Employee < Person

I get the following error:

Showing last frame. Use --error-trace for full trace.

error in line 13
Error: this 'initialize' doesn't initialize instance variable '@person_name' of Person, with Employee < Person, rendering it nilable

Of course if I change the person_name to name, the code works (I don't want to this).

Note:

For example the similar solution in Python:

class Person:
    def __init__(self, person_name):
        self.person_name = person_name
    def greet_person(self):
        print("Hi {}".format(self.person_name))

class Employee(Person):
    def __init__(self, name, company_name):
        Person.__init__(self, person_name=name)
        self.name = name
        self.company_name = company_name
    def greet_employee(self):
        print("Hi {} in {} company".format(self.name, self.company_name))

bob = Person("bob")
bob.greet_person()

john = Employee("john", "acme")
john.greet_person()
john.greet_employee()

Output:

Hi bob
Hi john
Hi john in acme company

Upvotes: 0

Views: 164

Answers (1)

Johannes M&#252;ller
Johannes M&#252;ller

Reputation: 5661

One solution is the super keyword. It calls the same method on the parent type. In this case, put super(@name) in Employee#initialize and it calls Person#initialize with @name as argument.

Alternatively, you can assign @person_name = @name manually in Employee#initialize instead of calling the super method to do that.

However, you might want to reconsider your object model. Having two pretty much identical instance variables doesn't seem like a good idea. Maybe I'm missing something so, like that the values of these ivars can change independently of each other and the identical initialization is just so start things off.

EDIT: Added code sample.

class Employee < Person
  # alternative 1:
  def initialize(@name : String, @company_name : String)
    super(@name)
  end
  # alternative 2:
  def initialize(@name : String, @company_name : String)
    @person_name = @name
  end
end

Upvotes: 1

Related Questions