2010-12-13 69 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