如何检查定义的方法?来自在类中使用的模块,其中包含模块后定义的方法
Posted
技术标签:
【中文标题】如何检查定义的方法?来自在类中使用的模块,其中包含模块后定义的方法【英文标题】:How to check method_defined? from a module thats used in class with a method defined after the module is included 【发布时间】:2021-08-26 00:17:17 【问题描述】:如何定义一个模块来检查使用该模块的类中是否存在实例方法。该模块通常包含在文件的开头,而方法是在之后定义的。我正在使用 Rails。
带有钩子的模块
module MyModule
extend ActiveSupport::Concern
included do
raise "Foo" if method_defined? :bar
end
end
以下代码中从未引发Foo
错误,我怎样才能让这个引发错误?
class MyClass
include MyModule
def bar
puts "Hello from Bar"
end
end
以下代码中出现Foo
错误:
class MyOtherClass
def bar
puts "Hello from Bar"
end
include MyModule
end
【问题讨论】:
Ruby 在类定义中执行指令,就像任何其他指令序列一样,一条一条地执行。当时include MyModule
,MyClass
还没有bar
。您需要一台时间机器才能知道bar
将在未来被定义。
写一个异常块。如果未定义该方法,它将引发错误,因此您可以使用一些代码块来挽救它
【参考方案1】:
这是一个纯 Ruby 的答案。我不知道 Rails 是否支持 Ruby 不支持的回调,这在这里有用。
正如@Amadan 所说,该模块不是读心器;要查看在类上定义的实例方法,需要在包含模块之前定义该方法。方法Module#included 将包含它的模块作为参数。它需要它,因为在执行该方法时,self
是 MyModule
。
module MyModule
def self.included(mod)
puts "self = #self"
puts ":bar is defined" if mod.method_defined? :bar
puts ":foo is defined" if mod.method_defined? :foo
puts ":goo is defined" if mod.method_defined? :goo
end
def goo
end
end
class MyClass
def bar
end
include MyModule
end
打印
self = MyModule
:bar is defined
:goo is defined
注意Module#included
是在MyModule
(goo
)中定义的实例方法包含在MyClass
之后执行的。
【讨论】:
MyModule
不必是读心者,也可以是观察者。可以使用Module#method_added
来观察bar
的定义并在该事件中引发。以上是关于如何检查定义的方法?来自在类中使用的模块,其中包含模块后定义的方法的主要内容,如果未能解决你的问题,请参考以下文章