2011-04-29 10 views
5
def moo 
    puts "moo" 
end 

moo.moo.moo.moo 

esto da¿Por qué un método de rubí tienen como método

moo 
moo 
moo 
moo 

simplemente una rareza, tenía curiosidad si esto fue hecho a propósito y se sirve un propósito ...

+1

Acabo de intentar esto en el IRB y no voy a conseguir el mismo resultado. ¿Cómo estás escribiendo este script y cómo lo estás ejecutando? – Mario

+0

¿qué versión de ruby? y ¿tiene algo más que sea un objeto primordial? Como si lo pruebo en 1.9.2-p180 obtengo 'NoMethodError: método privado 'moo' llamado para nil: NilClass' – Doon

+0

@Mario En IRB, Ruby 1.8.7 - No estoy seguro si hay una forma especial de ejecutarlo;) – npiv

Respuesta

5

supongo que está haciendo que en la consola, entonces realmente estás definiendo el método en el Object, que luego define el método en todos los hijos de Object ... que es todo. Por lo que su método:

def moo 
    puts "moo" 
end 

devoluciones nil, y debido a que ha definido el método de Object, NilClass tiene el método, así, para que pueda llamar moo en NilClass.

Si lo hace:

class Foo 
    def bar 
    1 + 1 
    end 
end 

Y luego:

f = Foo.new 
f.bar.bar 

Se obtiene:

NoMethodError: undefined method `bar' for 2:Fixnum 
+0

¡respuesta increíble, gracias! ¿Esto es específico para mi versión entonces, o aún un comportamiento constante en el 1.9 IRB? – npiv

+4

Cambia en '1.9'. 'irb' en' 1.9' realmente define el método como un método de instancia privado en 'main', que es el objeto con el que' irb' se ejecuta. – jaredonline

+1

Además, su método en 'irb 1.9' también devolverá una instancia de' String', que no tiene definido el método 'moo', por lo que obtendrá' NoMethodError'. – jaredonline

0

puts "moo" retornos nil. Un método de un alcance se puede utilizar en cualquier ámbito a continuación. Como moo se encuentra en la parte superior alcance, todos los objetos se llaman:

"teste".moo # => prints "moo" 

Si usted no quiere que, hacen moo privada:

private :moo 
moo # => ok 
nil.moo # => NoMethodError 
moo.moo # => prints once and raise NoMethodError 
0

Eso no debería trabajar.

Está definiendo moo como un método en el objeto 'principal'. Llamar a moo debería funcionar, pero tu método devuelve nil (porque puts devuelve nil). No definiste NilClass # moo, por lo que moo.moo debería fallar, y lo hace por mí.

+0

Es interesante.Obtengo un 'método privado 'moo' llamado para nil: NilClass ' error, no un' método indefinido 'moo' para nil: NilClass 'como esperaba. – steenslag

+0

@steenslag sí, yo también. No estoy seguro de lo que está pasando allí. – noodl

+4

No está definiendo moo como un método en el objeto principal (que sería 'def self.foo'), lo está definiendo como un método de instancia privada en Object. De cualquier manera 'moo.moo' todavía no debería funcionar. Sin embargo, en ruby ​​1.8 hubo una inconsistencia que hizo que los métodos definidos "globalmente" fueran públicos en lugar de privados (en irb, pero no en el rubí normal), lo que explica por qué el OP vería el comportamiento que ve. – sepp2k

1

Quizás esté definiendo algo en la clase Object. Como todo en Ruby es Object y todos los métodos devuelven algo (valor predeterminado a nil), puede llamar a ese método según su propio resultado. El método moo devuelve nil, por lo que lo que está haciendo es llamar al moo primero en el objeto global, y luego en cada nil devuelto.

Usted puede hacer más explícita la siguiente:

class Object 
    def moo 
    puts 'moo' 
    end 
end 

Si por lo general quiere métodos de la cadena, puede probar esto:

class Mooer 
    def moo 
    puts 'moo' 
    self 
    end 
end 

a = Mooer.new 
a.moo.moo.moo.moo.inspect 
Cuestiones relacionadas