开发者

checking if a method is defined on the class

How do I check if a method is defined on some class directly, not by inheritance or by inclusion/extension? I want something like 'foo?' in the following:

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


Use this:

C.instance_methods(false).include?(:a)
C.instance_methods(false).include?(:b)
C.instance_methods(false).include?(:c)

The method instance_methods return an Array of methods that an instance of this class would have. Passing false as first parameter returns only methods of this class, not methods of super classes.

So C.instance_methods(false) returns the list of methods defined by C.

Then you just have to check if that method is in the returned Array (this is what the include? calls do).

See docs


For objects you can use Object.respond_to?.

Returns true if obj responds to the given method.

For classes take a look at Module.instance_methods

Returns an array containing the names of the public and protected instance methods in the receiver.


Not exactly an answer to the question, but if you're reading this question, you might be interested in this, which uses .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

For example

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)

yields

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]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜