проверка, определен ли метод в классе - PullRequest
26 голосов
/ 01 февраля 2011

Как проверить, определен ли метод в каком-либо классе напрямую, а не наследованием или включением / расширением?Я хочу что-то вроде '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 ]

42 голосов
/ 01 февраля 2011

Используйте это:

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?).

См. Документы

27 голосов
/ 01 февраля 2011

Для объектов вы можете использовать Object.respond_to? .

Возвращает true, если obj отвечает на данный метод.

Для классов принятьвзгляд на Module.instance_methods

Возвращает массив, содержащий имена методов открытого и защищенного экземпляра в получателе.

0 голосов
/ 10 июня 2017

Не совсем ответ на вопрос, но если вы читаете этот вопрос, вас это может заинтересовать, в котором используется .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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...