Respostas:
A gravação @age
acessa diretamente a variável de instância @age
. A gravação self.age
diz ao objeto para enviar a mensagem para si mesma age
, que geralmente retornará a variável de instância @age
- mas poderia fazer várias outras coisas, dependendo de como o age
método é implementado em uma determinada subclasse. Por exemplo, você pode ter uma classe MiddleAgedSocialite que sempre relata sua idade 10 anos mais nova do que realmente é. Ou, na prática, uma classe PersistentPerson pode ler preguiçosamente esses dados de um armazenamento persistente, armazenar em cache todos os dados persistentes em um hash.
A diferença é que está isolando o uso do método da implementação. Se a implementação da propriedade mudar, digamos, para manter a data de nascimento e, em seguida, calcular a idade com base na diferença de tempo entre agora e a data de nascimento, o código, dependendo do método, não precisa ser alterado. Se ela usasse a propriedade diretamente, a alteração precisaria se propagar para outras áreas do código. Nesse sentido, o uso direto da propriedade é mais frágil do que a interface fornecida pela classe.
Esteja avisado quando você herdar uma classe da Struct.new
qual é uma maneira elegante de gerar um inicializador ( Como gerar o inicializador no 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()
retornará
30
nil
No entanto, quando você remover o inicializador, ele retornará
nil
30
Com a definição de classe
class Node2
attr_accessor :value
def initialize(value)
@value = value
end
def show()
p @value
p self.value
end
end
Você deve fornecer o construtor.
n2 = Node2.new(30)
n2.show()
retornará
30
30
A primeira resposta está totalmente correta, mas como um novato relativo, não ficou imediatamente claro para mim o que isso implicava (enviar mensagens para si mesmo? Uh huh ...). Eu acho que um pequeno exemplo ajudará:
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
Não há diferença. Suspeito que isso tenha sido feito apenas pelo valor documental de nos vermos self.age
e nos other_person.age
aproximarmos.
Suponho que o uso permita que um getter real seja gravado no futuro, o que pode fazer algo mais complexo do que apenas retornar uma variável de instância e, nesse caso, o método não precisaria ser alterado.
Mas é uma abstração improvável se preocupar, afinal, se a implementação do objeto mudou, é razoável alterar outros métodos, em algum momento uma simples referência dentro do próprio objeto é perfeitamente razoável.
De qualquer forma, a abstração da age
propriedade ainda não explica o uso explícito de self
, como simplesmente age
também teria invocado o acessador.
@age - é definitivamente a variável de instância age
self.age - refere-se à idade da propriedade da instância.