2009-10-04 10 views
5
class A 
    do_something_from_b 

    def method_in_a 
    end 
end 

module B 
    def self.included base 
    base.extend ClassMethods 
    end 

    module ClassMethods 
    def do_something_from_b 
     A.class_eval do 
     alias_method :aliased_method_in_a, :method_in_a 
     end 
    end 
    end 
end 

A.send(:include, B) 

do_somethind_from_bが呼び出されるとき、method_in_aがまだ存在していないので、このコードは失敗しますロードされます。実行コードが完全に

だから、それが完全にロードされた後、class Aにフックclass Aの終わりにdo_something_from_bコールを入れせずにする方法は何ですか?

:指摘したように、コードには他にも問題がありますが、それはポイントの横にあります。私は、私が達成したいことを説明するだけで、の後にいくつかのコードが実行されます。クラスは閉じられています(問題なく再開できます)。そして今、私はそれがおそらく不可能であることを知っています。

ありがとうございます!

+0

「この作品を作るにはどうすればいいのか」という壊れたものがコメントアウトされた実例を投稿することをお勧めします。この場合、それは単なる1行であるべきですが、このコードはさまざまな方法で壊れているようです... – DigitalRoss

+3

また、rubyクラスはオープンなので、クラスが完全にロードされた時点は決してありません。 –

+0

サム、リマインダーのおかげで。だから私はそれのために、私が望むことをするのは不可能だと思う。 – Ivan

答えて

5

Rubyでは、クラスが完全に読み込まれることはありません。あなたはいつでもそれを開くことができます。

class A 
    def method_in_a 
    … 
    end 
end 

あなたのコードが(別のソースコードファイルであっても)後で行うことができます。

(前のコードとまったく同じである)
class A 
    alias :aliased_method_in_a :method_in_a 
end 

またはあなたはそれをあなたがそれを書いた方法を行うことができ

A.class_eval do 
    alias :aliased_method_in_a :method_in_a 
end 

あなたは#1 method_in_aを指摘したように、あなたがそれを別名時点で存在している必要があります。これが真実であることを確認するには、エイリアスを実行する前に、

require "file_of_class_a" 

を実行する前に行うことができます。方法#1 method_in_aが作成されたときに、あなたがわからない場合、あなたは

class A 
    def self.method_added(name) 
    alias :aliased_method_in_a :method_in_a if name == :method_in_a 
    end 
end 

Aのメソッドが定義されますたびA.method_addedが自動的に呼び出されますを行うことができます。

+0

johannes、私は十分にあなたに感謝することはできません。その方法は非常に便利です。私はそれがパフォーマンスヒットかもしれないと思うが、あまりにも偉大ではないことを望みましょう。 ところで、私は "プレーン"エイリアスで何が起こるか分かりませんが、Railsのalias_method_chainを使用しています。これは無限ループでmethod_addedをトリガーします。したがって、クラス変数を使用してメソッドすでにエイリアス化されていました。 – Ivan

+1

ここにmethod_addedに関する情報があります:http://blog.sidu.in/2007/12/rubys-methodadded.html – Ivan

+0

私は単純なエイリアスでテストしましたが、再帰は発生しませんでした。 – johannes

関連する問題