Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

checking if a method is defined on the class

Tags:

ruby

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
like image 467
sawa Avatar asked Feb 01 '11 16:02

sawa


People also ask

What is IS_A in Ruby?

The is_a? method will return a true value if an object is a of the type given as a parameter OR if it inherits from the type given as a parameter. So in effect, you can use it to ask "is there going to be a method from a class which I can run on this object".


3 Answers

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

like image 135
Arnaud Le Blanc Avatar answered Sep 28 '22 04:09

Arnaud Le Blanc


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.

like image 22
miku Avatar answered Sep 28 '22 04:09

miku


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]
like image 21
Tim Rosenblatt Avatar answered Sep 28 '22 05:09

Tim Rosenblatt