Crystal - 将实例变量传递给父 class

Crystal - Pass instance variable to parent class

我有一个 Crystal 继承代码。

这是一个工作代码,不包含继承

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,代码就可以工作(我不想这样)。

注:

例如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