在多个Class #extend调用上

时间:2015-01-23 10:57:57

标签: ruby decorator singleton-methods

考虑来自this article的代码:

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的每次调用都会在实例单例类祖先链中添加一个模块,如下所述。

2 个答案:

答案 0 :(得分:2)

extend添加到祖先列表中,它不会替换任何现有的祖先 - 如果您在第二次扩展后检查coffee.singleton_class.ancestors,则可以看到它包含Milk和{ {1}}。

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

super_method

这表明如果你称'成本',你首先要去'糖'模块的实现

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

这表明在coffee.method(:cost).super_method => #<Method: Coffee(Milk)#cost> 中您拨打Sugar#cost,然后您将跳转到super提供的方法

最后

Milk

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

答案 1 :(得分:0)

你总是只有#cost被未来的争论所修改 - 这不是被覆盖的问题:

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

文章说这个实现与它们提供的其他基于继承的示例相同。