Risposte:
La scrittura @age
accede direttamente alla variabile di istanza @age
. La scrittura self.age
dice all'oggetto di inviare se stesso il messaggio age
, che di solito restituirà la variabile di istanza @age
, ma potrebbe fare qualsiasi numero di altre cose a seconda di come age
viene implementato il metodo in una determinata sottoclasse. Ad esempio, potresti avere una classe MiddleAgedSocialite che riporta sempre la sua età di 10 anni più giovane di quanto non sia in realtà. O più praticamente, una classe PersistentPerson potrebbe leggere pigramente quei dati da un archivio persistente, memorizzare tutti i dati persistenti in un hash.
La differenza è che sta isolando l'uso del metodo dalla sua attuazione. Se l'implementazione della proprietà dovesse cambiare - diciamo per mantenere la data di nascita e quindi calcolare l'età in base alla differenza temporale tra ora e la data di nascita - allora il codice a seconda del metodo non deve cambiare. Se utilizzava direttamente la proprietà, la modifica avrebbe dovuto propagarsi ad altre aree del codice. In questo senso, l'uso diretto della proprietà è più fragile dell'uso dell'interfaccia fornita dalla classe.
Stai attento quando erediti una classe da Struct.new
cui è un modo chiaro per generare un inizializzatore ( Come generare un inizializzatore in 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()
sarà di ritorno
30
nil
Tuttavia, quando si rimuove l'inizializzatore, verrà restituito
nil
30
Con la definizione della classe
class Node2
attr_accessor :value
def initialize(value)
@value = value
end
def show()
p @value
p self.value
end
end
Dovresti fornire il costruttore.
n2 = Node2.new(30)
n2.show()
sarà di ritorno
30
30
La prima risposta è del tutto corretta, ma come newbie relativo non mi è stato subito chiaro cosa implicasse (inviare messaggi a se stessi? Uh eh ...). Penso che un breve esempio aiuterà:
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
Non c'è alcuna differenza. Sospetto che sia stato fatto apposta per il valore documentario di vedere self.age
e other_person.age
avvicinarsi.
Suppongo che l'uso consenta di scrivere in futuro un vero getter, il che potrebbe fare qualcosa di più complesso che restituire semplicemente una variabile di istanza, e in tal caso il metodo non dovrebbe cambiare.
Ma è un'astrazione improbabile di cui preoccuparsi, dopo tutto, se l'implementazione dell'oggetto è cambiata è ragionevole cambiare altri metodi, ad un certo punto un semplice riferimento all'interno dell'oggetto stesso è perfettamente ragionevole.
In ogni caso, l'astrazione della age
proprietà non spiega ancora l'uso esplicito di self
, in quanto semplicemente age
avrebbe invocato l'accessor.
@age - è sicuramente l'età variabile dell'istanza
self.age: si riferisce all'età della proprietà dell'istanza.