红宝石物体可以在“祖父母”上打电话吗?

时间:2013-05-18 22:58:23

标签: ruby metaprogramming

如果我的课程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]

如果我希望salad.chewchew中触发Spinach方法而不将super添加到Dressing #chew,那可能吗?有没有办法达到两级(与super“达到”一级上升的方式相同)?

3 个答案:

答案 0 :(得分:4)

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

(有关用法示例,请参阅Using the Object.inspect / Object.to_s on a class derived from Hash上的其他答案)

答案 1 :(得分:1)

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

super关键字的目的是:您可以创建一个类,将其子类化,覆盖一个方法,并向该方法添加一些新行为,同时仍然执行该方法最初执行的所有操作。 super有效地说:“现在执行此方法的默认行为”。无论是否在超类,超类,模块或其他任何地方定义了“默认”行为,这都可行。

答案 2 :(得分:1)

如果您想知道如何在所有模块上调用chew方法,那么有一个更好的解决方案是使用合成。模块用于行为,如果你考虑你的Salad类,你不希望它的行为像菠菜或杏仁,你希望它由它们组成。所以当你chew给你一个沙拉时chew