2011-03-14 12 views
8

Estoy muy confundido por el comportamiento de Ruby al definir const_missing y otros métodos de clase dentro de una definición class << self en lugar de usar la sintaxis def self.foo.Missing constant y "const_missing" dentro de la definición "class << self"

yo estaba tratando de hacer algo como esto:

class Foo 
    class << self 
    def foo 
     puts MISSING 
    end 

    def const_missing(name) 
     puts "#{name} missing" 
    end 
    end 
end 

Foo.foo 

sobre todo me usan la sintaxis de la class << self para definir los métodos de clase. Sin embargo, no funcionó como se esperaba. const_missing nunca se llama. Lo anterior da como resultado un NameError.

Definición de ambos métodos como esto funciona como se espera:

def self.foo 
    puts MISSING 
end 

def self.const_missing(name) 
    puts "#{name} missing" 
end 

pensé que la sintaxis class << self es sólo otra manera de definir los métodos de clase, pero completamente equivalente a def self.foo? He probado lo anterior con MRI 1.8.7, 1.9.2 y JRuby 1.5.6. Entonces, obviamente me falta algo aquí?

Cualquier sugerencia es muy apreciada.

Gracias, Martin

Respuesta

12

class << self no es un atajo para definir los métodos de clase. Esta sintaxis (no sé el nombre exacto) abre la clase de usuario de un objeto (en su caso, una clase). Con eso puedes definir métodos para el objeto (no métodos de instancia). Pero cuando llamas una constante a la clase de origen, estás llamando a una constante de la clase de origen, no de la clase. En este caso hay que definir un método de clase en los eigenclass a los const_missing, dos maneras de hacerlo:

class Test 
    class << self 
    def foo 
     p MISSING 
    end 

    # First way: (syntax sugar for the second way) 
    def self.const_missing(name) 
     name 
    end 

    # Second way: 
    class << self # eigenclass of the eigenclass of the class 
     def const_missing(name) 
     name 
     end 
    end 

    end 
end 

Test.foo #=> :MISSING 
+0

Muchas gracias, LBG. Sabía que 'class << self' abre la clase propia de una clase. Pero como los métodos de clase son solo métodos de instancia de la clase de genes, pensé que funcionaría de esta manera. Sin embargo, tiene mucho sentido que una constante a la que se hace referencia desde la clase de origen no sea lo mismo que una constante a la que se hace referencia desde la propia clase. A veces todo esto hace que mi cabeza gire :) – martido

Cuestiones relacionadas