Reputation: 5329
I have a Crystal code with inheritance.
Person
is my parent class and it has a person_name
string parameter in the initialize
method.Employee
is the child class and it is inherited from Person
, it has 2 input parameters: name
and company_name
.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).
name
variable to person_name
?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
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