2010-12-13 70 views
2

我有点麻烦了解什么时候可以调用“超级”,什么时候不可以。在下面的例子中,super方法导致没有超类错误。在重新定义方法中访问超类方法的问题

class Bacterium 
    def eats 
    puts "Nam" 
    end 
end 

class Bacterium 
    def eats 
    super # -> no superclass error 
    puts "Yam" 
    end 
end 

b = Bacterium.new 
b.eats 

但这个工程:

class Fixnum 
    def times 
    super # -> works 
    puts "done" 
    end 
end 

5.times { |i| puts i.to_s } 

是5不仅仅是也Fixnum对象的实例。我是不是像上面的细菌例子那样重新定义现有的方法?

回答

3

不,不是真的。 Fixnum继承自Integer类,并且实际上你重写Integer#times,所以super可以工作,因为它会从父级调用实现。

为了在monkeypatching时达到类似的效果,在重新定义它之前应该使用别名方法,并在别处调用它。

class Bacterium 
    alias_method :eats_original, :eats 
    def eats 
    eats_original # -> "Nam" 
    puts "Yam" 
    end 
end 

类别重新开放不是一种继承形式,super是没有用的。

+0

谢谢,很好的解释!现在绝对清楚。 – Zardoz 2010-12-13 10:29:03

3

正如姆拉登说,你可以检查与Class#superclass

irb> Fixnum.superclass 
=> Integer 

而且也整数实现#times

irb> Integer.instance_methods.grep /times/ 
=> [:times] 

是它。

所以,我们可以用简化的方式说,超级调用你所在的超类的方法。在你的情况下,Bacterium的超类是Object,它不实现#eats

我说,这是非常简单的,因为看看这个例子:

module One 
    def hi 
    " World" << super() 
    end 
end 

module Two 
    def hi 
    "Hello" << super() 
    end 
end 

class SayHi 
    def hi 
    "!!!" 
    end 
end 

h = SayHi.new 
h.extend(One) 
h.extend(Two) 

puts h.hi 

#=> Hello World!! 

别拿严重的是我写到这里,它实际上是Ruby对象模型的冰山,这是尖重要的是要理解(我仍然在学习它) - 那么你将获得大部分或所有这些概念。

对于“Ruby对象模型”使用一些Google-fu ...

+0

感谢您的好例子。 Ruby是如此强大(但也导致其所有权力有时有点混乱)。 – Zardoz 2010-12-13 10:36:30

+0

我只想添加...如果在'hi'方法被定义之前,模块'One'被包含到'SayHi'中,''One''的'hi'可以在'SayHi'中作为'super'使用。所以订单似乎总是很重要。 – Zardoz 2010-12-13 10:39:59

+1

@Zardoz:恕我直言,关于Ruby的最好的事情并不是它的强大(正如许多其他现代语言一样),但是它没有为每个可能的功能添加特定的语法和关键字 - 语言保持精简和清洁。 'alias_method'和'extend'只是普通的方法,而不是语言结构或其他东西。 – 2010-12-13 11:46:20