2011-05-30 14 views
5

Teniendo en cuenta este código:¿Por qué no se resuelven estos métodos?

class Something 
    attr_accessor :my_variable 

    def initialize 
    @my_variable = 0 
    end 

    def foo 
    my_variable = my_variable + 3 
    end 
end 

s = Something.new 
s.foo 

consigo este error:

test.rb:9:in `foo': undefined method `+' for nil:NilClass (NoMethodError) 
    from test.rb:14:in `<main>' 

Si attr_accessor crea un método llamado my_variable (y .. =), ¿por qué no se puede encontrar el método foo? Funciona si lo cambio a self.my_variable, pero ¿por qué? ¿No es self el receptor predeterminado?

Respuesta

7

No está llamando al método allí, ¡en realidad está haciendo referencia a la misma variable que está en el proceso de definir! Esto es un poco complicado en Ruby.

Lo que sería mejor es si se hace referencia y establecer la variable de instancia en su lugar:

@my_variable = @my_variable + 3 

o más corto:

@my_variable += 3 

O puede llamar al método de selección, como lo encontró (y Jits pointed) fuera:

self.my_variable += 3 

Este último llamará al my_variable= método definido por attr_accessor, donde los otros dos solo modificarán una variable. Si lo hizo de esta manera, se podría anular my_variable= a hacer algo diferente para el valor pasado:

def my_variable=(value) 
    # do something here 
    @my_variable = value 
end 

PRIMA

O puede llamar al método explícitamente pasando un conjunto vacío de argumentos a través :

my_variable = my_variable() + 3 

esto no es "el camino Rubí" de hacerlo, pero aún así es interesante saber que todavía se puede llamar a un método de esta manera si usted tiene una variable local con el mismo nombre.

+1

WRT la bonificación: Aún necesitará configurar el ivar directamente o usar el colocador. Eso solo establece un local. – Chuck

5
my_variable = my_variable + 3 

... es una asignación variable local, que tiene prioridad.

De ahí la necesidad de self - con el fin de que alcance el objeto.

2

Creo que en este caso el alcance de la variable está solo dentro de la función, a menos que lo anteponga a self. de @.

Cuestiones relacionadas