2011-05-06 44 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" 

舊的酒吧仍然存在,現在只是有點難以訪問。

相關問題