你可以在Ruby中覆盖别名方法吗?

时间:2011-05-06 00:29:11

标签: ruby-on-rails ruby alias

在Ruby中,当方法有别名时,别名指向原始方法的主体。因此,即使重新定义原始方法,别名也将继续使用原始定义。

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

class Foo
  def bar
    "BAR"
  end
end

puts Foo.new.saloon

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

4 个答案:

答案 0 :(得分:5)

重新建立别名:

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"

答案 1 :(得分:3)

class Foo
  def bar
    "bar"
  end
  def saloon
    bar
  end
end

这根本不是别名,但可以按照您的意愿使用。

答案 2 :(得分: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
顺便说一句,如果有人可以剥离其中一个步骤,我可以知道吗! :)

答案 3 :(得分:1)

是和否。 coreyward或Sony Santos的解决方案都运行良好。您需要知道的是为什么您的编码不会像您那样工作。

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"

旧酒吧仍然存在,现在只是稍微难以访问。