[英]Improving on hacky ruby 'method_alias' fix for conflicting redmine plugins?
[英]ruby method_alias in inherited class
我正在深入研究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使用兩次時會導致錯誤。 解決此類問題的最佳方法是什么? 如何確定是否存在混合並在新混合之前將其刪除
遵循方法的定義以了解為什么會發生這種情況。
首先定義Example1::example
中的類定義Example1
。 它將字符串寫入控制台。
然后,擴展ExampleAliaser
。 當您調用Example1::do_example_alias
,然后將方法example
別名為origin_example
並重新定義該方法example
以將不同的字符串寫入控制台並調用origin_example
。
然后,定義要從Example1
繼承的類Example2
,該類現在在上面定義了兩個方法: 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
刪除不再需要定義的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.