2016-10-13 9 views
1

私はクラスBaseと、Baseを継承する2つのクラスDerivedDerived2を持っています。それぞれには、関数fooが定義されています。Rubyクラス階層における `prepend`の振る舞い

私はモジュールGenも持っています。これはprepend-Baseです。また、prepend-Derived2になりますが、Derivedにはなりません。

IはDerived2のインスタンスにfooを呼び出すとGenモジュールのみprependBaseになくDerived2に-edたかのように、結果です。これは期待される行動ですか?ここで

は、上記のシナリオのためのコードです:

module Gen 
    def foo 
    val = super 
    '[' + val + ']' 
    end 
end 

class Base 
    prepend Gen 

    def foo 
    "from Base" 
    end 
end 

class Derived < Base 
    def foo 
    val = super 
    val + "from Derived" 
    end 
end 

class Derived2 < Base 
    prepend Gen 
    def foo 
    val = super 
    val + "from Derived" 
    end 
end 

Base.new.foo  # => "[from Base]" 

Derived.new.foo # => "[from Base]from Derived" 

Derived2.new.foo # => "[from Base]from Derived" 

Iを出力する上記の文の最後の期待:あなたが理解するため

[[from Base]from Derived] 

答えて

3

を、方法Class#ancestorsがあり、これはメソッドが検索される順序を指示します。この場合は:あなたが言ったクラスのインスタンスであるオブジェクトのメソッドを呼び出すとき

Base.ancestors  # => [Gen, Base, Object, Kernel, BasicObject] 
Derived.ancestors # => [Derived, Gen, Base, Object, Kernel, BasicObject] 
Derived2.ancestors # => [Gen, Derived2, Gen, Base, Object, Kernel, BasicObject] 

ので、その方法は、その順序で対応するリストで検索されます。

  • Prependingは、そのリストの前にモジュールを配置します。
  • 継承すると、親のチェーンが子の最後に置かれます(正確ではありませんが、単純化のため)。
  • ちょうどが「チェーンをさらに横断して、同じ方法を見つける」と言っています。 Base中とGenのその -

Baseのために、我々は2つのfooの実装を持っています。 Genが最初に見つかるでしょう。従って= [from Base]superを介して)、ならびにチェーンを検索するであろう、Gen#foo= [S]を呼び出すBaseのインスタンスでそれを呼び出します。

Derivedについては、モジュールが前に付いていないため、継承があります。そのため、最初の実装を見つけ= [from Base]from Derived(上の段落が再生される別名)Derived= Sfrom DerivedsuperBaseから来ているチェーンの残りの部分を検索することです。方法= [S]第が発見されるようDerived2について

は、モジュールは、付加されています。その後superDerived2の次foo = [Sfrom Derived]があります、とsuperBase再び= [[from Base]from Derived]のための状況をそこに再生されます。


EDIT:それはごく最近までそれをアップしそうです、prependは最初の祖先チェーンで検索するでしょうし、(includeと同様に)それはまだ存在しない場合にのみ、モジュールを追加します。さらに混乱させるために、最初に親を作成し、それを継承し、子を前に付けてから親に追加すると、新しいバージョンの結果が得られます。

+0

'prepend'が動作する方法を知っています。しかし、先祖の鎖は、あなたが上に印刷したものにはならなかった。 1. 'Base.ancestors#=> [Gen、Base、Object、Kernel、BasicObject]' 2. Derived.ancestors#=> [Derived、Gen、Base、Object、Kernel、BasicObject] ' 3。 'Derived2.ancestors#=> [Derived2、Gen、Base、Object、Kernel、BasicObject]' 私はRuby 2.2.4を使用しています。 – CppNoob

+0

@CppNoobがアップデートを追加しました。 – ndn

+0

この動作の変更がどのバージョンで有効になったのか知っていますか? – CppNoob

関連する問題