Crystal - 将实例变量传递给父 class
Crystal - Pass instance variable to parent class
我有一个 Crystal 继承代码。
Person
是我的父 class,它在 initialize
方法中有一个 person_name
字符串参数。
Employee
是子 class 继承自 Person
,它有 2 个输入参数:name
和 company_name
。
这是一个工作代码,不包含继承:
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
输出:
Hi, Bob person
It is something
Hi, John in Acme company
如果我实现继承:
class Employee < Person
我收到以下错误:
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
当然,如果我将 person_name
更改为 name
,代码就可以工作(我不想这样)。
- 如果 parent/child class 中的变量名称不相同会怎样?
- 如何将
name
变量的值传递给 person_name
?
注:
- 我使用的是 0.36.1 Crystal 版本
例如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()
输出:
Hi bob
Hi john
Hi john in acme company
一个解决方案是 super
关键字。它在父类型上调用相同的方法。在这种情况下,将 super(@name)
放入 Employee#initialize
并调用 Person#initialize
并以 @name
作为参数。
或者,您可以在 Employee#initialize
中手动分配 @person_name = @name
而不是调用超级方法来执行此操作。
但是,您可能需要重新考虑您的对象模型。拥有两个几乎相同的实例变量似乎不是一个好主意。
也许我遗漏了一些东西,比如这些 ivar 的值可以相互独立地更改,并且相同的初始化只是开始。
编辑:添加了代码示例。
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
我有一个 Crystal 继承代码。
Person
是我的父 class,它在initialize
方法中有一个person_name
字符串参数。Employee
是子 class 继承自Person
,它有 2 个输入参数:name
和company_name
。
这是一个工作代码,不包含继承:
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
输出:
Hi, Bob person
It is something
Hi, John in Acme company
如果我实现继承:
class Employee < Person
我收到以下错误:
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
当然,如果我将 person_name
更改为 name
,代码就可以工作(我不想这样)。
- 如果 parent/child class 中的变量名称不相同会怎样?
- 如何将
name
变量的值传递给person_name
?
注:
- 我使用的是 0.36.1 Crystal 版本
例如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()
输出:
Hi bob
Hi john
Hi john in acme company
一个解决方案是 super
关键字。它在父类型上调用相同的方法。在这种情况下,将 super(@name)
放入 Employee#initialize
并调用 Person#initialize
并以 @name
作为参数。
或者,您可以在 Employee#initialize
中手动分配 @person_name = @name
而不是调用超级方法来执行此操作。
但是,您可能需要重新考虑您的对象模型。拥有两个几乎相同的实例变量似乎不是一个好主意。 也许我遗漏了一些东西,比如这些 ivar 的值可以相互独立地更改,并且相同的初始化只是开始。
编辑:添加了代码示例。
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