如何检查方法是否直接在某个类上定义,而不是通过继承或包含/扩展?我想要'foo'之类的东西?在下面:
class A
def a; end
end
module B
def b; end
end
class C < A
include B
def c; end
end
C.foo?(:a) #=> false
C.foo?(:b) #=> false
C.foo?(:c) #=> true
答案 0 :(得分:42)
使用此:
C.instance_methods(false).include?(:a)
C.instance_methods(false).include?(:b)
C.instance_methods(false).include?(:c)
方法instance_methods
返回此类实例所具有的方法数组。传递false
作为第一个参数只返回此类的方法,而不是超类的方法。
因此C.instance_methods(false)
会返回C
定义的方法列表。
然后你只需要检查该方法是否在返回的数组中(这是include?
调用所做的)。
答案 1 :(得分:27)
对于对象,您可以使用Object.respond_to?。
如果obj响应给定的方法,则返回true。
对于课程,请查看Module.instance_methods
返回一个数组,其中包含接收器中公共和受保护实例方法的名称。
答案 2 :(得分:0)
不完全是问题的答案,但如果你正在阅读这个问题,你可能对此感兴趣,使用.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]