2010-12-13 12 views
2

「スーパー」を呼び出すことができない場合とそうでない場合を理解するのが少し面倒です。以下の例では、スーパーメソッドはスーパークラスエラーを発生しません。メソッドの再定義でスーパークラスメソッドにアクセスする際の問題

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 } 

はFixnumかの5だけではなく、インスタンスです。私は上記のBacteriumの例のような既存のメソッドを再定義していませんか?

答えて

3

いいえ、実際はありません。 FixnumIntegerクラスから継承し、実際にはInteger#timesをオーバーライドしているので、superが動作します。これは、親から実装を呼び出すためです。

monkeypatchingのときに同様のことを実現するには、メソッドを別名で再定義してからエイリアスで呼び出す必要があります。再開

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

クラスは、継承の形ではなく、superが役に立ちません。ムラデンが言ったのと同じように

+0

ありがとう、非常によく説明されています!今は絶対にクリアしてください。 – Zardoz

3

、あなたはClass#superclassていることを確認することができます。

irb> Fixnum.superclass 
=> Integer 

を整数で#timesを実装しない:?

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

をはいそれはありません。

したがって、単純な方法で、スーパーはあなたがスーパークラスのメソッドを呼び出すと言うことができます。あなたのケースでは、BacteriumのスーパークラスはObjectであり、#eatsを実装していません。

私はこの例を見ているので、これは、非常に単純化していると述べた:それはある、実際にRubyのオブジェクトモデルの氷山の一角である、

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オブジェクトモデル"にはいくつかのGoogle-fuを使用しています...

+0

いい例をありがとう。 Rubyはとても強力です(しかし、時にはすべての力が混乱することもあります)。 – Zardoz

+0

ちょうど私が追加したいのは、 'hi'メソッドが定義される前に' SayHi'モジュールに 'One'モジュールが含まれている場合、' SayHi'の '' one'の '' hi''が 'super'として利用可能です。したがって、注文は常に重要であるようです。 – Zardoz

+1

@Zardoz:IMHO、Rubyについての最善のことは、他の多くの現代の言語がそうであるように、強力ですが、可能なすべての機能に特定の構文とキーワードを追加しなくても実現できるということではありません。 'alias_method'と' extend'は普通のメソッドであり、言語の構文ではありません。 –

関連する問題