variable modulos herencia clases clase ruby instance-variables

modulos - Usar variables de instancia en métodos de clase-Ruby



modulos ruby (2)

Esas son variables de instancia de clase y son cosas perfectamente legítimas en ruby: las clases también son objetos (instancias de clase) y también tienen variables de instancia.

Una cosa a tener en cuenta es que cada subclase tendrá su propio conjunto de variables de instancia de clase (después de todos estos son objetos diferentes): si se subclasificó DummyClass , los métodos de clase en la subclase no podrían ver @arr .

Las variables de clase ( @@foo ) son, por supuesto, al revés: toda la jerarquía de clases comparte las mismas variables de clase.

Soy muy nuevo en ruby ​​(en realidad soy c # dev.), Por lo que esta pregunta podría ser novato. Tengo una clase como la siguiente, y utilicé variables de instancia (matriz) para evitar el uso de muchos parámetros de método.

Funciona como esperaba, pero ¿es una buena práctica? En realidad, no esperaría que funcionase, pero supongo que los métodos de clase no funcionan como métodos estáticos en otros idiomas, así que me pregunto si es una buena práctica o si puedo enfrentar problemas como actuar esas variables como variables de clase y jugar Todo arriba.

class DummyClass def self.dummy_method1 @arr = [] # Play with that array end def self.dummy_method2 # use @arr for something else end end


La razón por la cual las variables de instancia funcionan en las clases en Ruby es que las clases de Ruby son instancias mismas (instancias de 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.

Como 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ía llamar ::DummyClass.instance_variable_get(:@arr) y obtener el valor actual de esa variable de instancia.

En cuanto a si es algo bueno, depende de los métodos .

Si @arr es lógicamente el "estado" de la instancia / clase DummyClass , entonces guárdela en la variable de instancia. Si @arr solo se usa en dummy_method2 como un atajo operativo, páselo como argumento. Para dar un ejemplo donde se usa el enfoque de variable de instancia, considere ActiveRecord in Rails. Te permite hacer esto:

u = User.new u.name = "foobar" u.save

Aquí, el nombre que se ha asignado al usuario son datos que están legítimamente en el usuario. Si, antes de la llamada #save , uno fuera a preguntar "¿cuál es el nombre del usuario en este momento?", 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 usado contiene dos invocaciones públicas separadas. Para ver un caso en el que las variables de instancia aún se utilizan a pesar de que solo se realizó una llamada, consulte la implementación de ActiveRecord de #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 ) a pesar de que 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 donde las variables de instancia no tendrían sentido usar. Observe 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 normalmente #link_to , como la URL a la que enlazar. Cuando la condición booleana es verdadera, necesita pasar el resto de los argumentos a #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.