委托给包含的模块

时间:2018-01-24 02:22:50

标签: ruby

Ruby(2.5)中是否有办法以相同的方式调用包含模块中定义的方法super用于继承?

我的意思是,假设我有以下

class Parent
 def name
  "parent"
 end
end

class Child < Parent
  def name
   "my parent is #{super}"
  end
end

当我致电Child.new.name时,我会my parent is parent

如何在以下情况下实现相同目标?

module Parent
 def name
  "parent"
 end
end

class Child 
  include Parent

  def name
   "my parent is #{???}"
  end
end

我应该将???替换为什么?

谢谢

2 个答案:

答案 0 :(得分:6)

您仍然可以使用super

module Parent
 def name
  "parent"
 end
end

class Child 
  include Parent

  def name
   "my parent is #{super}"
  end
end

Child.new.name # => "my parent is parent"

当包含模块时,ruby会将此模块添加到继承链。

Child.ancestors # => [Child, Parent, Object, Kernel, BasicObject]

因此,在super中调用Child将调用其祖先中的相应方法。

答案 1 :(得分:2)

我们获得了模块Parent

module Parent
  def name
    "parent"
  end
end

和班级Child

class Child 
  include Parent    
  def name
    "my parent is #{super}"
  end
end

正如@Tai指出的那样,我们可以使用super来获取:

Child.new.name
  #=> "my parent is parent"

,因为

Child.ancestors
  #=> [Child, Parent, Object, Kernel, BasicObject]

模块Parent在什么意义上是Child类的“父”?是的,这些只是单词,但它具有误导性。

现在让我们创建另一个模块并让Child包含它。

module A
  def name
    "A"
  end
end

Child.include A
Child.new.name
  #=> "my parent is A"

,因为

Child.ancestors
  #=> [Child, A, Parent, Object, Kernel, BasicObject]

我们看到将Class#name定义如下更为清楚:

def name
  "the last module included is #{super}"
end

让我们再试一次:使用Module#prepend

module B
  def name
    "B"
  end
end

Child.prepend B
Child.new.name
  #=> "B"

“我的父母是B”,因为

Child.ancestors
  #=> [B, Child, A, Parent, Object, Kernel, BasicObject]

表示B#name(不调用super)已执行(不是Child#name)。这意味着如果已经预先安装了任何模块,结果就毫无意义。