检查是否在类上定义了方法
如何检查方法是否直接在某个类上定义,而不是通过inheritance或包含/扩展? 我想要’foo’之类的东西? 在下面的:
class A def a; end end module B def b; end end class C false C.foo?(:b) #=> false C.foo?(:c) #=> true
用这个:
C.instance_methods(false).include?(:a) C.instance_methods(false).include?(:b) C.instance_methods(false).include?(:c)
方法instance_methods
返回此类的实例将具有的方法Array。 将false
作为第一个参数传递仅返回此类的方法,而不返回超类的方法。
因此, C.instance_methods(false)
返回C
定义的方法列表。
然后你只需要检查该方法是否在返回的数组中(这是include?
调用的内容)。
查看文档
对于对象,您可以使用Object.respond_to? 。
如果obj响应给定方法,则返回true。
对于类,请查看Module.instance_methods
返回一个数组,其中包含接收器中公共和受保护实例方法的名称。
不完全是问题的答案,但是如果你正在阅读这个问题,你可能会对此感兴趣,它使用.instance_methods(false)
class Object # This is more or less how Ruby does method lookup internally def who_responds_to?(method, klass_ancestors = nil) if klass_ancestors.nil? return who_responds_to?(method, self.class.ancestors) end if klass_ancestors.empty? return nil end if klass_ancestors[0].instance_methods(false).include?(method) return klass_ancestors[0] end klass_ancestors.shift who_responds_to?(method, klass_ancestors) end end
例如
class Person end module Drummer def drum end end module Snowboarder def jump end end module Engineer def code end end class Bob < Person include Drummer include Snowboarder include Engineer def name end end puts "who responds to name" puts bob.who_responds_to?(:name) puts "\n" puts "who responds to code" puts bob.who_responds_to?(:code) puts "\n" puts "who responds to jump" puts bob.who_responds_to?(:jump) puts "\n" puts "who responds to drum" puts bob.who_responds_to?(:drum) puts "\n" puts "who responds to dance" puts bob.who_responds_to?(:dance)
产量
who responds to name Bob who responds to code Engineer who responds to jump Snowboarder who responds to drum Drummer who responds to dance [this line intentionally blank because return value is nil]