Jak działa to podejście do tworzenia metody klasy prywatnej:
class Person
def self.get_name
persons_name
end
class << self
private
def persons_name
"Sam"
end
end
end
puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name #=> raises "private method `persons_name' called for Person:Class (NoMethodError)"
Ale to nie:
class Person
def self.get_name
persons_name
end
private
def self.persons_name
"Sam"
end
end
puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name
ruby
access-specifier
99 mil
źródło
źródło
Odpowiedzi:
private
nie działa, jeśli definiujesz metodę na obiekcie jawnym (w twoim przypadkuself
). Możesz użyćprivate_class_method
do zdefiniowania metod klasowych jako prywatnych (lub tak, jak opisano).Alternatywnie (w Ruby 2.1+), ponieważ definicja metody zwraca symbol nazwy metody, możesz również użyć tego w następujący sposób:
źródło
ExiRe napisał:
Może to być mylące, może być frustrujące, ale zdecydowanie nie jest obrzydliwe.
Ma to sens, gdy zrozumiesz model obiektowy Ruby i przepływ odnośnych metod , szczególnie biorąc pod uwagę, że NIE
private
jest to modyfikator dostępu / widoczności, ale w rzeczywistości wywołanie metody (z klasą jako odbiorcą), jak omówiono tutaj ... w Ruby nie ma czegoś takiego jak „sekcja prywatna” .Aby zdefiniować prywatne metody instancji , wywołujesz
private
klasę instancji, aby ustawić domyślną widoczność dla później zdefiniowanych metod na prywatne ... i dlatego sensowne jest definiowanie prywatnych metod klasy poprzez wywołanieprivate
klasy klasy, tj. jego metaklasa.Inne główne, samozwańcze języki OO mogą dawać mniej mylącą składnię, ale zdecydowanie wymieniasz to na mylący i mniej spójny (niespójny?) Model obiektowy bez możliwości narzędzi do metaprogramowania Ruby.
źródło
private_class_method :method_name
możesz to zrobićprivate_class_method def method_name...
.send(private_method)
jest również dostępny poza obiektem.private_class_method def self.method_name
Domyślnie wszystkie metody klas są publiczne. Aby ustawić je jako prywatne, możesz użyć Module # private_class_method jak napisał @tjwallace lub zdefiniować je inaczej, tak jak zrobiłeś:
class << self
otwiera singletonową klasę self, dzięki czemu można przedefiniować metody dla bieżącego obiektu self. Służy do definiowania metody klasa / moduł („statyczna”). Tylko tam zdefiniowanie metod prywatnych naprawdę daje metody klasy prywatnej.źródło
Dla kompletności możemy również uniknąć zadeklarowania metody private_class_metod w osobnym wierszu. Osobiście nie lubię tego użycia, ale dobrze wiedzieć, że istnieje.
źródło
Ja też uważam, że Ruby (a przynajmniej moja wiedza na ten temat) nie ma znaku w tym obszarze. Na przykład poniższe czynności robią to, co chcę, ale są niezdarne,
Moje problemy z powyższym kodem polegają na tym, że wymagania dotyczące składni Ruby i metryki jakości kodu są zgodne z tym, co jest kłopotliwe. Aby kod działał tak, jak chcę, i wyciszać metryki, muszę zrobić z metody replace () metodę klasy. Ponieważ nie chcę, aby był on częścią publicznego API klasy, muszę być prywatny, ale sam „prywatny” sam w sobie nie działa. Zamiast tego jestem zmuszony użyć metody „private_class_method” lub innej takiej metody. To z kolei wymusza użycie „self.class.send (: porównaj ...” dla każdej zmiennej, którą testuję w „== ()”. Teraz jest to trochę niewygodne.
źródło
Metody instancji są zdefiniowane w bloku definicji klasy. Metody klasowe są zdefiniowane jako metody singletonowe w klasie singleton klasy, zwanej także nieformalnie „metaklasą” lub „klasą elektroniczną”.
private
nie jest słowem kluczowym, ale metodą ( moduł nr prywatny ).Jest to wywołanie metody
self#private
/,A#private
które „włącza” prywatny dostęp do wszystkich przyszłych definicji metod instancji, dopóki nie zostanie przełączone inaczej:Jak wspomniano wcześniej, metody klasowe są tak naprawdę metodami singletonowymi zdefiniowanymi w klasie singleton.
Lub używając specjalnej składni, aby otworzyć treść definicji anonimowej, singletonowej klasy A:
Odbiorca „wiadomości prywatnej” - self - inside
class A
jest obiektem klasy A. self wewnątrzclass << A
bloku to kolejny obiekt, klasa singleton.Poniższy przykład w rzeczywistości wywołuje dwie różne metody nazywane prywatnymi , używając dwóch różnych odbiorców lub celów połączenia. W pierwszej części definiujemy metodę instancji prywatnej („w klasie A”), w drugiej definiujemy metodę klasy prywatnej (w rzeczywistości jest to metoda singletonu na obiekcie klasy singleton A).
Teraz przepisz trochę ten przykład:
Czy widzisz błąd [popełniony przez projektantów języka Ruby]? Przełączasz na dostęp prywatny dla wszystkich przyszłych metod instancji klasy A, ale kontynuujesz deklarowanie metody singleton w innej klasie, klasie singleton.
źródło
Ruby wydaje się słabym rozwiązaniem. Aby wyjaśnić, zacznij od prostego przykładu C ++, który pokazuje dostęp do metod klasy prywatnej:
Uruchamianie powyższego
Teraz Ruby nie wydaje się odpowiadać. Sądzę, że zasady Ruby mówią, że nie można uzyskać dostępu do prywatnych metod za pomocą odbiornika. To jest,
To jest OK w przypadku metod instancji prywatnej, ale powoduje problemy z metodami klasy prywatnej.
Chciałbym, aby Ruby działała w ten sposób:
Ale niestety powyższe nie działa. Czy ktoś zna lepszy sposób?
Kiedy widzę „wyślij” przed metodą, jest to wyraźny znak, że kod narusza intencję projektanta API, ale w tym przypadku projekt ma konkretnie wywołać metodę instancji klasy wywołującą metodę klasy prywatnej.
źródło
Od ruby 2.3.0
źródło
private def self.second_method
każdą notacją metody, która nie działała na moim ruby 2.3.3. Ale ten zapis działa dla mnie.Check.second_method
również działałoby bez problemu, więc nie jest tak naprawdę prywatne.private_class_method :second_method