Zmienna instancji: self vs @
Oto jakiś kod:
class Person
def initialize(age)
@age = age
end
def age
@age
end
def age_difference_with(other_person)
(self.age - other_person.age).abs
end
protected :age
end
Chcę wiedzieć, jaka jest różnica między użyciem @age
i self.age
w metodzie age_difference_with
.
6 answers
Zapis @age
bezpośrednio uzyskuje dostęp do zmiennej instancji @age
. Writing self.age
mówi obiektowi, aby sam wysłał wiadomość age
, która zazwyczaj zwraca zmienną instancji @age
- ale może wykonać wiele innych czynności w zależności od tego, jak Metoda age
jest zaimplementowana w danej podklasie. Na przykład możesz mieć klasę MiddleAgedSocialite, która zawsze zgłasza swój wiek o 10 lat młodszy niż w rzeczywistości. Lub bardziej praktycznie, Klasa PersistentPerson może leniwie odczytać te dane ze sklepu trwałego buforuj wszystkie jego trwałe DANE w hash.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-07 15:08:24
Różnica polega na tym, że izoluje zastosowanie metody od jej implementacji. Jeśli implementacja właściwości miała się zmienić-powiedzmy, aby zachować datę urodzenia, a następnie obliczyć wiek na podstawie różnicy w czasie między datą teraz a datą urodzenia-wtedy kod w zależności od metody nie musi się zmieniać. Jeśli użyje tej właściwości bezpośrednio, to zmiana musiałaby rozprzestrzeniać się na inne obszary kodu. W tym sensie korzystanie z nieruchomości bezpośrednio jest bardziej kruche niż za pomocą dostarczonego mu interfejsu klasy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-07 14:41:52
Bądź ostrzeżony, gdy dziedziczysz klasę z Struct.new
co jest dobrym sposobem na wygenerowanie intializera ( Jak wygenerować initializer w Rubim?)
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()
Powróci
30
nil
Jednak po usunięciu inicjalizatora zwróci
nil
30
Z definicją klasy
class Node2
attr_accessor :value
def initialize(value)
@value = value
end
def show()
p @value
p self.value
end
end
Powinieneś podać konstruktor.
n2 = Node2.new(30)
n2.show()
Powróci
30
30
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:33
Nie ma żadnej różnicy. Podejrzewam, że zrobiono to tylko dla dokumentalnej wartości widzenia self.age
i other_person.age
blisko siebie.
Przypuszczam, że użycie pozwala na zapisanie rzeczywistego gettera w przyszłości, co może zrobić coś bardziej złożonego niż tylko zwrócenie zmiennej instancji, a w takim przypadku metoda nie musiałaby się zmieniać.
Ale to mało prawdopodobna abstrakcja, o którą należy się martwić, w końcu, jeśli implementacja obiektu uległa zmianie, rozsądne jest, aby zmień inne metody, w pewnym momencie proste odniesienie w samym obiekcie jest całkowicie rozsądne.
W każdym razie, abstrakcja właściwości age
nadal nie wyjaśnia jawnego użycia self
, ponieważ zwykły age
również wywołałby accessor.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-07 14:53:29
Pierwsza odpowiedź jest całkowicie poprawna, ale jako względny nowicjusz nie od razu zrozumiałam, co to oznacza (wysyłanie wiadomości do siebie? uh huh...). Myślę, że krótki przykład pomoże:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-04 13:52:17
@ age - to na pewno zmienna wieku instancji
Self.age-odnosi się do właściwości instance age.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-06 01:26:24