1

考虑本文中的代码:

class Coffee
  def cost
    2
  end
end

module Milk
  def cost
    super + 0.4
  end
end

module Sugar
  def cost
    super + 0.2
  end
end

coffee = Coffee.new
coffee.extend(Milk)
coffee.extend(Sugar)
coffee.cost   # 2.6, while I expected 2.2

它是 2.6 而不是 2.2 的原因是因为每次调用都会extend将一个模块添加到实例单例类祖先链中,如下所述。

4

2 回答 2

2

extend添加到祖先列表中,它不会替换任何现有的祖先 - 如果您coffee.singleton_class.ancestors在第二次扩展后检查,您会发现它同时包含MilkSugar

如果您运行的是 2.2,则可以使用新super_method方法来检查:

coffee.method(:cost) => #<Method: Coffee(Sugar)#cost>

这表明,如果您调用“成本”,则首先转到“糖”模块的实现

coffee.method(:cost).super_method => #<Method: Coffee(Milk)#cost>

这表明在Sugar#cost您调用super时,您将跳转到由Milk

最后

coffee.method(:cost).super_method.super_method => #<Method: Coffee#cost>

当您从那里调用 super 时,您最终会进入基类实现

于 2015-01-23T15:25:53.693 回答
0

你总是只拥有#cost由未来参数修改的 - 这不是被覆盖的问题:

coffee = Coffee.new
#cost is 2
coffee.extend(Milk)
#cost is 2.4
coffee.extend(Sugar)
#cost is 2.6

这篇文章说这个实现与他们给出的其他基于继承的示例相同。

于 2015-01-23T11:03:42.377 回答