far*_*adf 11 ruby alias ruby-on-rails
在Ruby中,当方法有别名时,别名指向原始方法的主体.因此,即使重新定义原始方法,别名也将继续使用原始定义.
class Foo
def bar
"bar"
end
alias :saloon :bar
end
class Foo
def bar
"BAR"
end
end
puts Foo.new.saloon
Run Code Online (Sandbox Code Playgroud)
将返回'bar'而不是'BAR'.有没有办法让轿车使用新的酒吧定义?
编辑:我应该更清楚.这个例子只是一个问题的例子 - 这不是我需要解决的实际问题.当你有链式别名时,问题就更复杂了,例如,在rails的核心中.例如,perform_action由基准测试模块别名,然后由flash模块.所以现在对perform_action的调用实际上是调用perform_action_with_flash执行它的事情,然后有效地调用perform_action_with_benchmarking然后调用原始的perform_action.如果我想覆盖perform_action_with_benchmarking(即使我同意这是一个坏主意 - 请让我们不要讨论它,因为除了这一点),我不能,因为它已被别名,并且据我所知别名指向的是原始perform_action_with_benchmarking的副本,所以即使重新定义它,也没有效果.
只需重新建立别名:
class Foo
def bar
"bar"
end
alias :saloon :bar
end
class Foo
def bar
"BAR"
end
alias :saloon :bar
end
puts Foo.new.saloon # => "BAR"
Run Code Online (Sandbox Code Playgroud)
这是另一个答案,但您必须执行一些额外的步骤:在覆盖之前收集别名,并在覆盖之后收集真实别名:
class Class
def get_aliases method_name
original_proc = instance_method method_name
aliases = []
instance_methods.each do |meth|
# if the methods have different names but they're the same, they're aliased
if meth != method_name.to_s && original_proc == instance_method(meth)
aliases << meth
end
end
aliases
end
end
class Foo
def bar
"bar"
end
alias :saloon :bar
end
class Foo
aliases = get_aliases :bar
def bar
"BAR"
end
aliases.each { |a| alias_method a, :bar }
end
puts Foo.new.saloon #=> BAR
Run Code Online (Sandbox Code Playgroud)
顺便说一句,如果有人可以去掉其中一个步骤,我可以知道吗!:)
| 归档时间: |
|
| 查看次数: |
1493 次 |
| 最近记录: |