我正在深入研究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次时会导致错误。 修复此类事情的最佳方法是什么?如何确定混合存在并在新混合之前将其移除
答案 0 :(得分:1)
按照方法的定义来了解发生这种情况的原因。
首先在Example1::example
的类定义中定义Example1
。它将一个字符串写入控制台。
然后你扩展ExampleAliaser
。当您致电Example1::do_example_alias
时,您将方法example
替换为origin_example
并重新定义方法example
,以便将另一个字符串写入控制台并调用origin_example
。
然后,您定义要从Example2
继承的班级Example1
,现在已定义了两个方法:origin_example
和example
。当您致电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
删除不再需要定义的方法。