¿Alguien puede decirme sobre la diferencia entre las variables de clase y las variables de instancia de clase?
Respuestas:
Una variable de clase ( @@
) se comparte entre la clase y todos sus descendientes. @
Los descendientes de la clase no comparten una variable de instancia de clase ( ).
Variable de clase ( @@
)
Tengamos una clase Foo con una variable de clase @@i
y accesos para leer y escribir @@i
:
class Foo
@@i = 1
def self.i
@@i
end
def self.i=(value)
@@i = value
end
end
Y una clase derivada:
class Bar < Foo
end
Vemos que Foo y Bar tienen el mismo valor para @@i
:
p Foo.i # => 1
p Bar.i # => 1
Y cambiar @@i
en uno lo cambia en ambos:
Bar.i = 2
p Foo.i # => 2
p Bar.i # => 2
Variable de instancia de clase ( @
)
Hagamos una clase simple con una variable de instancia de clase @i
y accesos para leer y escribir @i
:
class Foo
@i = 1
def self.i
@i
end
def self.i=(value)
@i = value
end
end
Y una clase derivada:
class Bar < Foo
end
Vemos que aunque Bar hereda los descriptores de acceso @i
, no se hereda a @i
sí mismo:
p Foo.i # => 1
p Bar.i # => nil
Podemos configurar Bar's @i
sin afectar a Foo's @i
:
Bar.i = 2
p Foo.i # => 1
p Bar.i # => 2
Primero debe comprender que las clases también son instancias, instancias de la Class
clase.
Una vez que comprenda eso, puede comprender que una clase puede tener variables de instancia asociadas con ella al igual que un objeto normal (léase: no clase).
Hello = Class.new
# setting an instance variable on the Hello class
Hello.instance_variable_set(:@var, "good morning!")
# getting an instance variable on the Hello class
Hello.instance_variable_get(:@var) #=> "good morning!"
Tenga en cuenta que una variable de instancia en no Hello
está relacionada y es distinta de una variable de instancia en una instancia deHello
hello = Hello.new
# setting an instance variable on an instance of Hello
hello.instance_variable_set(:@var, :"bad evening!")
# getting an instance variable on an instance of Hello
hello.instance_variable_get(:@var) #=> "bad evening!")
# see that it's distinct from @var on Hello
Hello.instance_variable_get(:@var) #=> "good morning!"
Una variable de clase, por otro lado, es una especie de combinación de las dos anteriores, ya que es accesible en Hello
sí misma y sus instancias, así como en subclases de Hello
y sus instancias:
HelloChild = Class.new(Hello)
Hello.class_variable_set(:@@class_var, "strange day!")
hello = Hello.new
hello_child = HelloChild.new
Hello.class_variable_get(:@@class_var) #=> "strange day!"
HelloChild.class_variable_get(:@@class_var) #=> "strange day!"
hello.singleton_class.class_variable_get(:@@class_var) #=> "strange day!"
hello_child.singleton_class.class_variable_get(:@@class_Var) #=> "strange day!"
Muchas personas dicen que se debe evitar class variables
debido al comportamiento extraño anterior y recomiendan el uso de class instance variables
.
También quiero agregar que puede obtener acceso a la variable de clase ( @@
) desde cualquier instancia de la clase
class Foo
def set_name
@@name = 'Nik'
end
def get_name
@@name
end
end
a = Foo.new
a.set_name
p a.get_name # => Nik
b = Foo.new
p b.get_name # => Nik
Pero no puede hacer lo mismo con la variable de instancia de clase ( @
)
class Foo
def set_name
@name = 'Nik'
end
def get_name
@name
end
end
a = Foo.new
a.set_name
p a.get_name # => Nik
b = Foo.new
p b.get_name # => nil
Foo.i
, pero ¿cómo puede hacer lo mismo para cada instancia de esta clase como Foo.new.i
?
#class
. Sin embargo, personalmente creo que los #class
usos se usan cuando se llama a cualquier cosa que no self
sean olores de código. Incluso puede ir un paso más allá e implementar accesos de instancia i
y i=
delegar a sus #class
equivalentes, en cuyo caso puede hacerlo Foo.new.i
. No recomiendo hacer eso ya que crea una interfaz confusa, lo que sugiere que está modificando un miembro del objeto.