gpt4 book ai didi

ruby - 不能通过包含模块来重新定义类的实例方法吗?

转载 作者:数据小太阳 更新时间:2023-10-29 07:56:51 25 4
gpt4 key购买 nike

我有一个急躁的时刻。我可以发誓这有效:

module StubbedGreeting
def sayit
puts "StubbedGreeting"
end
end

module RegularGreeting
def sayit
puts "RegularGreeting"
end
end

class Greeting
def sayit
raise "Gotta catch me!"
end
end

class GreetingIncludes
include RegularGreeting
end

begin
Greeting.send(:include, StubbedGreeting)
Greeting.new.sayit
rescue Exception
puts "Exception raised"
end

GreetingIncludes.send(:include, StubbedGreeting)
GreetingIncludes.new.sayit

这里发生的是 Greeting.new.sayit 导致调用 rescue block ,忽略 StubbedGreeting 尝试覆盖。

但是,GreetingIncludes.new.sayit 会导致“StubbedGreeting”,而不是异常(exception)。

所以一个模块可以覆盖另一个模块的方法,但不能覆盖已经在类中直接定义的方法?

我知道如何绕过这个问题,我只是觉得它很奇怪。

最佳答案

当包含一个模块时,它的方法按照方法解析顺序放在类的方法和它的父类的方法之间。所以在解析要调用哪个实际方法时,ruby首先按照以下顺序搜索方法。如果找到匹配的方法,则中止搜索并使用该方法。

  • 对象的单例类
  • 包含在单例类中的模块从最后包含到第一次包含
  • 对象的类别
  • 包含在类(class)中的模块

然后这对每个父类继续,直到达到 Class 类。

如您所见,模块确实不能覆盖在类本身上定义的方法,因为模块在方法解析顺序中位于实际类之后。如果你真的需要覆盖这样的方法,你可以使用 alias_methodalias_method_chain 来“重命名”方法。

在即将到来的 Ruby 2.0 中会有一个 prepend mechanism这将包括类(class)之前的模块,这些模块将实现您想要的。但它尚未发布。

关于ruby - 不能通过包含模块来重新定义类的实例方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12154274/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com