2

如果我有一个Salad带有方法的类chew并且我在其中使用super,它将调用沿chew祖先链向上的下一个可用方法。如果我想“达到两个级别”(到第二个可用的chew方法上链)怎么办?有没有办法在不添加super第一个祖先的方法的情况下做到这一点?

为了更具体一点,假设这是我的Salad类,有一个salad对象:

class Salad < Food
  include Almonds
  include Gorgonzola
  include Spinach
  include Dressing

  def chew
    super
  end
end

salad = Salad.new

祖先的数组将是这样的:

[Salad, Dressing, Spinach, Gorgonzola, Almonds, Food, Object, Kernel, BasicObject]

如果我想在不添加Dressing#chew 的情况下salad.chew触发该chew方法,这可能吗?有没有办法达到两个级别(以与 “达到”一个级别相同的方式)?Spinachsupersuper

4

3 回答 3

5

是的,有一种方法可以做您所描述的事情,这种方法是通过方法#method#instance_method,如method = Spinach.instance_method( :chew ),然后您可以将其绑定到沙拉或沙拉实例的元类,如method.bind( Salad ). 这种机制不像使用方便关键字那样简洁super,但提供了super's 功能的超集。还有更多细节,但相信我,这样,你可以做任何你想做的事。这就是 Ruby 的力量——你可以做任何事情,直到你需要 Lispiest 魔法,Ripper并且(迄今为止未完成)Sorcerer

(有关使用示例,请参阅我在从 Hash 派生的类上使用 Object.inspect / Object.to_s 的其他答案)

于 2013-05-19T03:14:49.057 回答
1

不,没有办法做你所描述的(并且有充分的理由)。您描述的“super-super”关键字的任何使用都将与您的继承链的细节(以及该链中的哪些类/模块实现给定方法)紧密耦合。它会很脆;如果存在这样的关键字,并且您使用了它,那么像移动方法定义这样的小改动很容易破坏事情。对于您的代码的读者来说,这也会非常混乱。

关键字的目的super是:您可以获取一个类、子类化它、覆盖一个方法,并向该方法添加一些新行为,同时仍然执行该方法最初所做的一切。super有效地说:“现在执行此方法的默认行为”。无论“默认”行为是在超类、超超类、模块还是其他任何地方定义的,它都有效。

于 2013-05-18T23:53:07.063 回答
1

如果您想知道如何实现chew在所有模块上调用该方法,有一个更好的解决方案是使用组合。模块是用于行为的,如果你考虑你的沙拉类,你不希望它表现得像菠菜或杏仁,你希望它由它们组成。因此,当您chew制作沙拉时,您将chew了解它的每一个组成部分。

于 2013-05-19T00:46:23.193 回答