2011-05-06 79 views
8

在Ruby中,当方法是别名时,别名指向原始方法的主体。因此,即使您重新定义了原始方法,别名仍将继续使用原始定义。你可以重写Ruby中的别名方法吗?

class Foo 
    def bar 
    "bar" 
    end 
    alias :saloon :bar 
end 

class Foo 
    def bar 
    "BAR" 
    end 
end 

puts Foo.new.saloon 

将返回'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的副本,所以即使我重新定义它,也没有任何效果。

+1

+1有趣(有趣)。 – 2011-05-06 01:22:13

回答

2

这里是另一个答案,但你必须做一些额外的步骤:收集后覆盖之前的别名和realias:

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 

BTW,的,如果任何人都可以去掉一个步骤,我可以知道它! :)

+0

这是确定哪些方法是别名的巧妙方法。我认为它会诀窍... – farhadf 2011-05-06 18:17:36

+0

我希望如此。谢谢! :) – 2011-05-06 18:40:39

4

刚刚重新建立别名:

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" 
3
class Foo 
    def bar 
    "bar" 
    end 
    def saloon 
    bar 
    end 
end 

这不是一个别名所有,但只要你想它的工作原理。

0

是的,没有。 Coreyward或索尼桑托斯的解决方案工作正常。你需要知道的是为什么你的编码不​​符合你的工作方式。

alias为该函数创建一个新的名称,就像调用该方法时出现的那样。这是不是的指针,而是一种指向某种东西的新方式。它允许我们做这样的事情:

class Foo 
    def bar 
    "bar" 
    end 
    alias :speakeasy :bar 
end 

class Foo 
    def bar(secret_code = false) 
    return speakeasy if secret_code == "A friend of Al" 
    "Closed because of prohibition!" 
    end 
end 

puts Foo.new.bar #=> "Closed because of prohibition!" 
puts Foo.new.bar "A friend of Al" #=> "bar" 

旧的酒吧仍然存在,现在只是有点难以访问。

相关问题