可以在 Ruby 中重写别名方法吗?

发布于 2024-11-05 02:46:08 字数 663 浏览 3 评论 0原文

在 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 由基准测试模块别名,然后也由闪存模块别名。所以现在对perform_action的调用实际上是调用perform_action_with_flash来完成它的事情,然后有效地调用perform_action_with_benchmarking,然后再调用原始的perform_action。如果我想覆盖perform_action_with_benchmarking(即使我同意这是一个坏主意 - 请让我们不要对此进行讨论,因为它超出了重点),我不能,因为它已被别名,并且据我所知别名本质上指向原始 Perform_action_with_benchmarking 的副本,因此即使我重新定义它,也没有效果。

In Ruby, when a method is aliased, the alias points to the body of the original method. So even if you redefine the original method, the alias will continue to use the original definition.

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

class Foo
  def bar
    "BAR"
  end
end

puts Foo.new.saloon

will return 'bar' and not 'BAR'. Is there any way to get saloon to use the new definition of bar?

EDIT: I should have been more clear. The example was just an illustration of the issue - it's not the actual problem I need to solve. The issue is more complex when you have chained aliases, for example, in rails' core. E.g. perform_action is aliased by benchmarking module, and then also by flash module. So now a call to perform_action is actually calling perform_action_with_flash which does it's thing, then effectively calls perform_action_with_benchmarking which then calls the original perform_action. If I want to override perform_action_with_benchmarking (even though I agree it's a bad idea - please let's not get into a discussion of that as it's besides the point), I can't because it has been aliased, and as far as I can tell the alias is pointing to what is essentially a copy of the original perform_action_with_benchmarking, so even if I redefine it, there's no effect.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

笑脸一如从前 2024-11-12 02:46:10

只需重新建立别名即可:

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"

Just re-establish the alias:

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"
思念满溢 2024-11-12 02:46:10
class Foo
  def bar
    "bar"
  end
  def saloon
    bar
  end
end

这根本不是别名,但它可以按照您的意愿工作。

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

This is not an alias at all, but it works as you want.

戏舞 2024-11-12 02:46:10

是和不是。 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"

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

Yes and no. Either coreyward or Sony Santos's solutions work fine. What you need to know is why your coded didn't work the way you though.

alias makes a new name for the function as is appears when the method is invoked. This is not a pointer, but a new way of referring to something. It allows us to do something like this:

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"

The old bar still exists, it just a little harder to access now.

ゞ花落谁相伴 2024-11-12 02:46:10

这是另一个答案,但您必须执行一些额外的步骤:在覆盖之前收集别名,并在覆盖之后收集真实别名:

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

顺便说一句,如果有人可以删除其中一个步骤,我可以知道吗! :)

Here is another answer, but you have to do some additional steps: collect the aliases before overriding, and realias after:

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, if anyone can strip off one of that steps, may I know it! :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文