2012-04-04 8 views
1

class_evalを使用していくつかのクラスの機能を拡張したいと思います。私はクラスに他のクラスからいくつかのメソッドを継承させたいと思います。Rubyのメタプログラミング:class_evalで継承を定義する

すなわち:

SomeClass.class_eval do 
    # force inheritence from some other class 
end 

それを達成するための最良の方法は何ですか?

答えて

1

既存の機能を上書きすることが難しい場合は、これらの既存のメソッドをモジュールに定義する必要があります。

class SomeClass 
    include DefaultBehaviour 
end 

module DefaultBehaviour 
    def run 
    puts "ran default" 
    end 
end 

module AlternateBehaviour 
    def run 
    puts "ran alternate" 
    end 
end 

SomeClass.class_eval { 
    include AlternateBehaviour 
} 

SomeClass.new.run #=> "ran alternate" 

ルビーのメソッドルックアップパスが原因です。

SomeClass - > Objectとして開始します。

AlternateBehaviourを含めると、SomeClass - > AlternateBehaviour - > Objectになります。したがって、SomeClassで直接定義されたメソッドが優先されます。

ただし、これらのメソッドがDefaultBehaviourで定義されている場合、ルックアップパスはSomeClass - > AlternateBehaviour - > DefaultBehaviour - > Objectになり、代替メソッドが優先されます。どのモジュールが最後に含まれていたかが最優先です。あなたは、元のクラスのコントロールを持っていない場合は、あなたが代わりに行うことができます場合は

module AlternateBehaviour 
    def self.included(base) 
    base.send(:remove_method, :run) 
    end 

    def run 
    puts "ran alternate" 
    end 
end 

この時点で、一つはあなただけ

を実行して、オフに良いかもしれないかどうかを疑問に開始しますが
SomeClass.class_eval { 
    def run 
    "ran alternate" 
    end 
end 
+0

複雑なのは、私がモジュールにリファクタリングすることができないサードパーティのエンジンコードの中に座っているクラスメソッドをオーバーライドしようとしているときです:(そうでなければあなたのソリューションは動作します... – alexs333

+0

それでは、ソリューションを更新してください。 – Burke

+0

なぜあなたはclass_evalを使う必要がありますか?メソッド定義を直接class_evalにダンプすることもできますし、置換メソッドを他の場所に配置したい場合は、置換を定義する前に既存のメソッドを削除するモジュールを作成することもできます。 – Burke

0

includeextendをお試しください。いずれもhereと記載されています。モジュールでのみ動作します。ただすることはできませんは、すでに作成された後にRubyでクラスのスーパークラスを変更/追加することはできません。

ただ1つの問題:この記事の3番目のコメントで説明されているクラスの既存のメソッドをオーバーライドすることはできません。

さらに詳しい情報については、thisトピックを参照してください。

+0

すでにクラスがあり、そのメソッドを外部モジュールで定義されているものからオーバーライドしたい場合はどうしたらいいですか? – alexs333

+0

投稿を更新しています... – Jwosty

+0

ルビはメソッドを見つけるために継承階層を後戻りさせ、クラスのすぐ上の階層にそのモジュールを挿入するだけなので、モジュールは実際にクラス自体で指定された機能をオーバーライドすることはありません。クラス自体は依然としてチェックされた最初の場所です。 ...これは、この問題の正しい解決策であると私はまだJwostyに同意します。クラスで既に定義されているメソッドを実際にオーバーライドする必要がある場合は、独自のモジュールで定義して解決できます。 – Burke

関連する問題