2012-03-03 14 views
6

Creo que me estoy volviendo un poco loco cuando trato de entender las variables de instancia en Ruby. Mi único objetivo aquí es asegurarme de que cada objeto creado para una clase determinada tenga una variable con un valor predeterminado sin escribiendo un método initialize para esa clase. Algo así como:Inicialización de variable de instancia en Ruby

class Test 

    @my = [] 

    attr_accessor :my 

end 
t = Test.new 
t.my # I want [] but this shows nil 

¿Es posible lograr esto sin tocar initialize? Gracias.

EDIT: Para aclarar, estoy escribiendo alguna pieza de código que se ejecutará similar a attr_accessor en el sentido de que va a añadir una variable de instancia de la clase en la que se ejecuta. Si escribo mi propio initialize, terminaré pegándome al escrito por el usuario.

Respuesta

11

Lo que está haciendo es definir una variable de instancia en el nivel de clase (dado que las clases son instancias de la clase Class, esto funciona bien).

Y no, no hay forma de evitar la inicialización.

Editar: Tiene un poco de error en su edición. attr_accessor no agrega una variable de instancia a la clase. Lo que hace, literalmente, es la siguiente (utilizando el ejemplo de my):

def my; @my; end 
def my=(value); @my = value; end 

No crea activamente/inicializar cualquier variable de instancia, sólo define dos métodos. Y bien podría escribir su propio método de clase que haga cosas similares, usando define_method.

Edición 2:

Para ilustrar mejor cómo se podría escribir un procedimiento de este tipo:

class Module 
    def array_attr_accessor(name) 
    define_method(name) do 
     if instance_variable_defined?("@#{name}") 
     instance_variable_get("@#{name}") 
     else 
     instance_variable_set("@#{name}", []) 
     end 
    end 

    define_method("#{name}=") do |val| 
     instance_variable_set("@#{name}", val) 
    end 
    end 
end 


class Test 
    array_attr_accessor :my 
end 

t = Test.new 
t.my # => [] 
t.my = [1,2,3] 
t.my # => [1, 2, 3] 
+0

Consulte la edición. – sasuke

+0

Malo, dije "similar a". Básicamente, este nuevo método, cuando se agrega a cualquier clase, como 'attr_accessor', agregará una nueva variable de instancia a todos los objetos creados para esa clase. – sasuke

+1

Ah, como pensaba, no puedo confiar en 'attr_reader' por defecto para tales atributos. Solo una última pregunta: ¿no hay forma de inicializar variables de instancia como la forma en que se hace para Java, etc. en Ruby? – sasuke

0

No creo que lo es, ¿por qué estás tan reacios a escribir sólo una inicialización rápida ¿método?

2
# as instance variable without initialize 
class Test1 
    def my; @my ||= [] end 

    attr_writer :my 
end 

t = Test1.new 
t.my 


# as class instance variable 
class Test2 
    @my = [] 

    class << self; attr_accessor :my end 
end 

Test2.my 
+1

+1, esp. para la variable de nivel de clase con los descriptores de acceso. Las variables de instancia de caveat re sin 'initialize' es que si intentas establecer' t.my = nil', 't.my' volverá a' [] 'debido a' || = ', lo cual es inesperado y puede que no ser deseado; Creo que es mejor no evitar 'initialize'. – mklement0

Cuestiones relacionadas