La razón variables de instancia de trabajo en clases en Ruby es que las clases de Ruby son casos propios (instancias de la clase Class). Pruébelo usted mismo inspeccionando DummyClass.class
. No hay "métodos estáticos" en el sentido de C# en Ruby porque cada método se define en (o se hereda) en alguna instancia y se invoca en alguna instancia. En consecuencia, pueden acceder a cualquier variable de instancia que esté disponible en el destinatario.
Dado que DummyClass
es una instancia, puede tener sus propias variables de instancia muy bien. Incluso puede acceder a esas variables de instancia siempre que tenga una referencia a la clase (que siempre debe ser porque los nombres de las clases son constantes). En cualquier punto, podrá llamar al ::DummyClass.instance_variable_get(:@arr)
y obtener el valor actual de esa variable de instancia.
En cuanto a si es una buena cosa hacer, depende de los métodos.
Si @arr
es lógicamente el "estado" de la instancia/clase DummyClass
, guárdelo en la variable de instancia. Si @arr
solo se usa en dummy_method2
como acceso directo operativo, páselo como argumento. Para dar un ejemplo donde se usa el enfoque de variable de instancia, considere ActiveRecord in Rails. Se le permite hacer esto:
u = User.new
u.name = "foobar"
u.save
Aquí, el nombre que se ha asignado al usuario es un dato que es legítimamente en el usuario. Si, antes de la llamada #save
, uno fuera a preguntar "¿cuál es el nombre del usuario en este punto", respondería "foobar". Si profundiza lo suficiente en las partes internas (excavará muy lejos y en una gran cantidad de metaprogramación, encontrará que utilizan variables de instancia para exactamente esto).
El ejemplo que he utilizado contiene dos invocaciones públicas distintas. Para ver un caso en el que las variables de instancia todavía se utilizan a pesar de que solo se realizó una llamada, consulte la implementación de ActiveRecord #update_attributes
. El cuerpo del método es simplemente load(attributes, false) && save
.¿Por qué #save
no pasa ningún argumento (como el nuevo name
) aunque va a estar en el cuerpo de guardar donde algo como UPDATE users SET name='foobar' WHERE id=1;
? Es porque cosas como el nombre es información que pertenece a la instancia.
Por el contrario, podemos ver un caso en el que las variables de instancia no tienen sentido de usar. Mire la implementación de #link_to_if
, un método que acepta un argumento boolean-ish (generalmente una expresión en el código fuente) junto con argumentos que son comúnmente aceptados por #link_to
, como la URL a la que se debe vincular. Cuando la condición booleana es verdadera, necesita pasar el resto de los argumentos al #link_to
e invocarlo. No tendría mucho sentido asignar aquí variables de instancia porque no diría que el contexto de invocación aquí (el representador) contiene esa información en la instancia. El renderizador en sí no tiene una "URL para vincular", y en consecuencia, no debe ser enterrado en una variable de instancia.
Gracias por esta gran explicación con ejemplos, especialmente sobre si es una buena práctica o no. – tackleberry