2011-12-23 163 views
9

假设我拥有从A类派生的类BRuby:调用子类中的父类的重写方法

是否可以像这样调用A的overrided方法?

class A 
    def method1 
    end 
    def method2 
    end 
end 

class B < A 
    def method1 
    ### invoke method2 of class A is what I want to do here 
    end 
    def method2 
    end 
end 

#不完全重复到How do I call an overridden parent class method from a child class?,但我们似乎想要做同样的事情。

+3

您的意思是说您的示例代码中B是A的子类? – sepp2k 2011-12-23 13:07:11

+1

如果b是一个子类,那么你可以简单地在你的b中调用super。 – three 2011-12-23 13:10:09

+1

不,他需要从后代的方法1调用super的method2。在Ruby中没有办法(我知道)要做到这一点。 – 2011-12-23 13:21:06

回答

16

我在这里假设B应该从A继承,而您只是在您的示例代码中犯了一个错字。如果情况并非如此,就没有办法做你想做的事情。

否则,你可以做你想做使用反射通过的Amethod2实例方法结合到当前的B对象并调用它像这样的内容:

class A 
    def method1 
    end 
    def method2 
    end 
end 

class B < A 
    def method1 
    A.instance_method(:method2).bind(self).call 
    end 
    def method2 
    end 
end 

不过请注意,你不应该拉出大除非你真的需要这样的黑魔枪。在大多数情况下,重新设计您的类层次结构以便您不需要这样做是更好的选择。

+0

谢谢。另一个魔术把我的袖子:-) – 2011-12-23 14:36:29

+0

+1我会张贴相同的东西。我也认为这很少,如果有的话,需要使用。为什么重写A#method2如果你仍然需要它在B?我只在尝试排除方法行为故障时使用绑定技巧,例如在irb。 – Kelvin 2011-12-26 21:47:29

9

可以使用alias语句创建一个父类的方法的代名词,从覆盖方法调用它:

class A 
    def method1 
    puts '1' 
    end 
    def method2 
    puts '2' 
    end 
end 

class B < A 
    alias parent_method1 method1 
    alias parent_method2 method2 
    def method1 
    parent_method2 
    end 
    def method2 
    end 
end 

b = B.new 
b.method1 # => 2 
5

@ sepp2k的答案是技术上是正确的,但是我想解释一下为什么这个技术不是适当的在我看来,(所以这个问题在技术上是有趣的,但导致了错误的目标):

  • 红宝石不允许调用super.method2method1称为B的一个实例的背景下,becau这是做错了。当你的实例是超类的特化时,应该使用类继承。这包括你通常只会扩展行为,通过调用super并在该调用之前或之后额外执行某些操作。
  • 有像Java和其他语言,允许调用超另一种方法,这导致类似于意大利面条代码,但面向对象的方式。没有人知道何时调用哪些方法,所以尽量避免它。

所以试着找出你想改变呼叫的原因并解决。如果你在A中的你的method1在B中实现了错误,那么你不应该子类化。

+0

“即使在思考@ sepp2k的答案是否正确时”是否有任何理由认为它不是? – sepp2k 2011-12-23 13:46:16

+0

对不起,我想表达你的答案在技术上是正确的,但这个问题本身就有缺陷。我会纠正它,对于那个误解抱歉。 – mliebelt 2011-12-23 14:06:51