privados - programacion con objetos ruby
Variables de clase Ruby (5)
Las cosas de la clase de Ruby me están dando dolor de cabeza. Entiendo dado esto ...
class Foo
@var = ''bar''
end
... que @var
es una variable en la instancia de la clase creada.
Pero, ¿cómo creo una variable de clase invalidable de subclase?
Aquí hay un ejemplo de lo que haría en Python:
class Fish:
var = ''fish''
def v(self):
return self.var
class Trout(Fish):
var = ''trout''
class Salmon(Fish):
var = ''salmon''
print Trout().v()
print Salmon().v()
Qué salidas:
trout
salmon
¿Cómo hago lo mismo en ruby?
Aquí está la versión que terminé averiguando usando el enlace de hobodave:
class Fish
class << self
attr_accessor :var
end
@var = ''fish''
def v
self.class.var
end
end
class Trout < Fish
@var = ''trout''
end
class Salmon < Fish
@var = ''salmon''
end
puts (Trout.new).v # => trout
puts (Salmon.new).v # => salmon
Tenga en cuenta que la @var
subclases solo requiere la adición de un @var
, no es necesario anular la inicialización.
Es un error común que hacen los programadores de Java al llegar a Ruby, y uno de los grandes saltos conceptuales que tuve que hacer para entenderlo. Al principio parece extraño, pero en realidad es uno de los aspectos más interesantes de Ruby: todo el código es ejecutable, incluidas las definiciones de clases.
Por lo tanto, las variables de instancia deben declararse dentro de los métodos. Tiene que ver con cómo se evalúa el "yo". ''uno mismo'' es el objeto actual. El intérprete buscará las llamadas al método y las referencias de variables primero en ''self'':
class Fish
@var = "foo" # here ''self'' == Fish, the constant which contains the class object
def foo
# do foo
end
end
fish = Fish.new
fish.foo # here ''self'' == fish, an instance of Fish
En una definición de clase, ''self'' se configura como el objeto de clase que se está definiendo, por lo que cualquier referencia dentro de una definición de clase se referirá a ese objeto de clase, en este caso Fish.
Sin embargo, cuando se invoca un método en una instancia de Fish, el self se establece para ser el receptor de la llamada, la instancia particular de Fish. Entonces, fuera de una definición de método, el yo es el objeto de clase. Dentro de un método, self es la instancia del receptor. Esta es la razón por la cual @var fuera de una definición de método es más parecido a una variable estática en Java, y @var dentro de una definición de método es una variable de instancia.
Hay un problema: puede anular @var:
Salmon.var = ''shark'' anulará @var, por lo
puts (Salmon.new) .v # => shark
Para contrastar la respuesta de @ khelll, esto usa variables de instancia en los objetos de clase:
class Fish
# an instance variable of this Class object
@var = ''fish''
# the "getter"
def self.v
@var
end
# the "setter"
def self.v=(a_fish)
@var = a_fish
end
end
class Trout < Fish
self.v = ''trout''
end
class Salmon < Fish
self.v = ''salmon''
end
p Trout.v # => "trout"
p Salmon.v # => "salmon"
Editar: para dar a las instancias acceso de lectura a la variable de instancia de la clase:
class Fish
def type_of_fish
self.class.v
end
end
p Trout.new.type_of_fish # => "trout"
p Salmon.new.type_of_fish # => "salmon"
@var
mencionado anteriormente se llama variable de instancia de clase , que es diferente de las variables de instancia ... lea la respuesta here para ver la diferencia.
De todos modos, este es el código Ruby equivalente:
class Fish
def initialize
@var = ''fish''
end
def v
@var
end
end
class Trout < Fish
def initialize
@var = ''trout''
end
end
class Salmon < Fish
def initialize
@var = ''salmon''
end
end
puts Trout.new.v
puts Salmon.new.v