继承类中的ruby方法别名

时间:2012-02-24 12:26:05

标签: ruby metaprogramming alias-method class-eval

我正在深入研究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次时会导致错误。 修复此类事情的最佳方法是什么?如何确定混合存在并在新混合之前将其移除

1 个答案:

答案 0 :(得分:1)

按照方法的定义来了解发生这种情况的原因。

首先在Example1::example的类定义中定义Example1。它将一个字符串写入控制台。

然后你扩展ExampleAliaser。当您致电Example1::do_example_alias时,您将方法example替换为origin_example并重新定义方法example,以便将另一个字符串写入控制台并调用origin_example

然后,您定义要从Example2继承的班级Example1,现在已定义了两个方法:origin_exampleexample。当您致电Example2::do_example_alias时,您将方法example别名为origin_example。但请记住example已经重新定义为origin_example。如此有效,Example2::example会调用自己,直到你的筹码用完为止。


如果你想避免双锯齿,你可以在do_example_alias中加入某种保护:

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

您也可以在子类中undef :method_name删除不再需要定义的方法。