在多个 Class#extend 通话中
On multiple Class#extend calls
考虑来自 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
都会将一个模块添加到实例单例 class 祖先链中,如下所述。
你总是只有 #cost
被未来的参数修改 - 这不是被覆盖的问题:
coffee = Coffee.new
#cost is 2
coffee.extend(Milk)
#cost is 2.4
coffee.extend(Sugar)
#cost is 2.6
文章说此实现与他们提供的其他基于继承的示例相同。
extend
添加到祖先列表中,它不会替换任何现有的祖先 - 如果您在第二次扩展后检查 coffee.singleton_class.ancestors
,您会看到它同时包含 Milk
和 Sugar
。
如果你是运行 2.2,你可以使用新的super_method
方法检查一下:
coffee.method(:cost) => #<Method: Coffee(Sugar)#cost>
这表明,如果您调用 'cost',您首先会转到 'Sugar' 模块的实现
coffee.method(:cost).super_method => #<Method: Coffee(Milk)#cost>
这表明在Sugar#cost
你调用super
然后你会跳转到Milk
提供的方法
最后
coffee.method(:cost).super_method.super_method => #<Method: Coffee#cost>
当您从那里调用 super 时,您最终进入基础 class 实现
考虑来自 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
都会将一个模块添加到实例单例 class 祖先链中,如下所述。
你总是只有 #cost
被未来的参数修改 - 这不是被覆盖的问题:
coffee = Coffee.new
#cost is 2
coffee.extend(Milk)
#cost is 2.4
coffee.extend(Sugar)
#cost is 2.6
文章说此实现与他们提供的其他基于继承的示例相同。
extend
添加到祖先列表中,它不会替换任何现有的祖先 - 如果您在第二次扩展后检查 coffee.singleton_class.ancestors
,您会看到它同时包含 Milk
和 Sugar
。
如果你是运行 2.2,你可以使用新的super_method
方法检查一下:
coffee.method(:cost) => #<Method: Coffee(Sugar)#cost>
这表明,如果您调用 'cost',您首先会转到 'Sugar' 模块的实现
coffee.method(:cost).super_method => #<Method: Coffee(Milk)#cost>
这表明在Sugar#cost
你调用super
然后你会跳转到Milk
最后
coffee.method(:cost).super_method.super_method => #<Method: Coffee#cost>
当您从那里调用 super 时,您最终进入基础 class 实现