2

ruby のメタプログラミングについて深く掘り下げていて、次の質問があります。例:

module ExampleAliaser
  def do_example_alias(prefix=:origin)

    class_eval  <<-EOS
       class << self 
           alias_method :#{prefix}_example, :example
           def example
              puts "in aliase will call :#{prefix}_example"
              #{prefix}_example
           end  
        end
    EOS

  end   
end  

class Example1
 def self.example
    puts "Example"
 end 
end


Example1.extend(ExampleAliaser)

class Example1 
 do_example_alias(:origin)
end
class Example2 <  Example1
 do_example_alias(:origin)
end



     Example1.example
    in aliase will call :origin_example
    Example
     => nil 

     Example2.example
in aliase will call :origin_example
in aliase will call :origin_example
in aliase will call :origin_example
    SystemStackError: stack level too deep
        from /Users/igorfedoronchuk/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/irb/workspace.rb:80
    Maybe IRB bug!!

そのため、mixin を 2 回使用するとエラーが発生します。そのようなものを修正する最良の方法は何ですか? 混合が存在することを確認し、新しい混合の前にそれを削除する方法

4

1 に答える 1

1

メソッドの定義に従って、これが起こっている理由を確認してください。

最初Example1::exampleに のクラス定義で定義しExample1ます。コンソールに文字列を書き込みます。

次に、拡張しExampleAliaserます。を呼び出すときは、メソッドをExample1::do_example_aliasにエイリアスし、メソッドexampleorigin_example再定義しexampleて別の文字列をコンソールに書き込み、 を呼び出しますorigin_example

Example2次に、から継承するクラスを定義します。これには、とExample1の 2 つのメソッドが定義されています。を呼び出すときは、メソッドを にエイリアスします。しかし、はすでに call に再定義されていることを思い出してください。効果的に、スタックのスペースがなくなるまで自分自身を呼び出します。origin_exampleexampleExample2::do_example_aliasexampleorigin_exampleexampleorigin_exampleExample2::example


二重エイリアスを回避したい場合は、ある種のガードを に含めることができますdo_example_alias:

def do_example_alias(prefix = :origin)
  unless methods.include?("#{prefix}_example")
    # do the aliasing
  end
end

undef :method_name定義したくないメソッドをサブクラスで削除することもできます。

于 2012-02-24T15:14:14.250 に答える