Respuestas:
Escribir @age
directamente accede a la variable de instancia @age
. Escribir self.age
le dice al objeto que se envíe el mensaje age
, que generalmente devolverá la variable de instancia @age
, pero podría hacer cualquier otra cantidad de cosas dependiendo de cómo age
se implemente el método en una subclase dada. Por ejemplo, puede tener una clase MiddleAgedSocialite que siempre informa que tiene 10 años menos de lo que realmente es. O más prácticamente, una clase PersistentPerson podría leer perezosamente esos datos de un almacén persistente, almacenar en caché todos sus datos persistentes en un hash.
La diferencia es que está aislando el uso del método de la implementación del mismo. Si la implementación de la propiedad cambiara, por ejemplo, mantener la fecha de nacimiento y luego calcular la edad en función de la diferencia de tiempo entre ahora y la fecha de nacimiento, entonces el código dependiendo del método no necesita cambiar. Si usaba la propiedad directamente, entonces el cambio necesitaría propagarse a otras áreas del código. En este sentido, usar la propiedad directamente es más frágil que usar la interfaz proporcionada por la clase.
Tenga en cuenta cuando herede una clase de la Struct.new
cual es una forma ordenada de generar un inicializador ( ¿Cómo generar un inicializador en Ruby? )
class Node < Struct.new(:value)
def initialize(value)
@value = value
end
def show()
p @value
p self.value # or `p value`
end
end
n = Node.new(30)
n.show()
volverá
30
nil
Sin embargo, cuando elimine el inicializador, volverá
nil
30
Con la definición de clase
class Node2
attr_accessor :value
def initialize(value)
@value = value
end
def show()
p @value
p self.value
end
end
Debes proporcionar el constructor.
n2 = Node2.new(30)
n2.show()
volverá
30
30
La primera respuesta es completamente correcta, pero como un novato relativo no me quedó claro de inmediato lo que implicaba (¿enviarse mensajes a uno mismo? Uh huh ...). Creo que un breve ejemplo ayudará:
class CrazyAccessors
def bar=(val)
@bar = val - 20 # sets @bar to (input - 20)
end
def bar
@bar
end
def baz=(value)
self.bar = value # goes through `bar=` method, so @bar = (50 - 20)
end
def quux=(value)
@bar = value # sets @bar directly to 50
end
end
obj = CrazyAccessors.new
obj.baz = 50
obj.bar # => 30
obj.quux = 50
obj.bar # => 50
No hay ninguna diferencia Sospecho que se hizo solo por el valor documental de verse self.age
y other_person.age
cerca el uno del otro.
Supongo que el uso permite que se escriba un captador real en el futuro, lo que podría hacer algo más complejo que simplemente devolver una variable de instancia, y en ese caso el método no necesitaría cambiar.
Pero es una abstracción poco probable de la que preocuparse, después de todo, si la implementación del objeto cambió, es razonable cambiar otros métodos, en algún momento una referencia simple dentro del objeto en sí es perfectamente razonable.
En cualquier caso, la abstracción de la age
propiedad todavía no explica el uso explícito de self
, ya que simplemente age
también habría invocado el descriptor de acceso.
@age: definitivamente es la edad variable de la instancia
self.age: se refiere a la antigüedad de la propiedad de instancia.