2011-02-01 43 views
22

¿Cómo puedo verificar si un método está definido en alguna clase directamente, no por herencia o por inclusión/extensión? Quiero algo como 'foo?' en la siguiente:comprobando si se define un método en la clase

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 

Respuesta

36

Utilice esta:

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

El método instance_methods devolver una matriz de métodos que una instancia de esta clase tendría. Al pasar false como primer parámetro, solo se devuelven los métodos de esta clase, no los métodos de superclase.

Así C.instance_methods(false) devuelve la lista de métodos definidos por C.

Luego solo tiene que comprobar si ese método está en la matriz devuelta (esto es lo que hacen las llamadas include?).

See docs

+0

Esto también se aplica a todos los casos. – sawa

+0

acaba de actualizar la respuesta; solo tiene que establecer el primer parámetro de instance_methods en falso para devolver solo los métodos definidos por C. – arnaud576875

+0

Lo tengo. Sabía que el método, pero no sabía que tomó ese parámetro. Gracias. – sawa

24

Para objetos que se pueden utilizar Object.respond_to?.

Devuelve true si obj responde al método proporcionado.

Para las clases de echar un vistazo a Module.instance_methods

Devuelve una matriz que contiene los nombres de los métodos de instancia públicas y protegidas en el receptor.

+0

Esto funcionará solo en instancias de las clases dadas :-) – arnaud576875

+0

Da verdadero a todos los casos C.new.foo?(:a), C.new.foo?(:b), C.new. foo? (: c) – sawa

+4

También tenga en cuenta que las clases * son * objetos, por lo que 'responder_ a?' también funciona en ellos. – bfontaine

0
No

exactamente una respuesta a la pregunta, pero si usted está leyendo esta pregunta, que podría estar interesado en este, que utiliza .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 

Por ejemplo

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) 

rendimientos

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] 
Cuestiones relacionadas