检查是否在类上定义了方法

时间:2011-02-01 16:57:25

标签: ruby

如何检查方法是否直接在某个类上定义,而不是通过继承或包含/扩展?我想要'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

3 个答案:

答案 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?调用所做的)。

See docs

答案 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]