W Scali widzę taką funkcję jak zmienna prywatna obiektu. Z mojego niezbyt bogatego zaplecza Java nauczyłem się zamykać wszystko (uczynić to prywatnym) i otwierać (udostępniać akcesory), jeśli to konieczne. Scala wprowadza jeszcze bardziej restrykcyjny modyfikator dostępu. Czy zawsze powinienem go używać domyślnie? A może powinienem go używać tylko w określonych przypadkach, w których muszę jawnie ograniczyć zmianę wartości pola nawet dla obiektów tej samej klasy? Innymi słowy, jak mam wybierać między
class Dummy {
private var name = "default name"
}
class Dummy {
private[this] var name = "default name"
}
Drugi jest bardziej rygorystyczny i mi się podoba, ale czy powinienem go używać zawsze, czy tylko z mocnego powodu?
EDYTOWANE: Jak widzę tutaj private[this]
jest tylko przypadek podrzędny i zamiast niego this
mogę użyć innych modyfikatorów: „pakiet, klasa lub obiekt pojedynczy”. Więc zostawię to na jakiś specjalny przypadek.
Odpowiedzi:
Nie sądzę, żeby to miało zbyt duże znaczenie, ponieważ wszelkie zmiany dotkną tylko jednej klasy. Tak najważniejszy powód do preferowania
private
przezprotected
ponadpublic
nie ma zastosowania.Używaj
private[this]
tam, gdzie wydajność naprawdę ma znaczenie (ponieważ uzyskasz bezpośredni dostęp do pola zamiast metod w ten sposób). W przeciwnym razie po prostu zdecyduj się na jeden styl, aby ludzie nie musieli zastanawiać się, dlaczego ta właściwość istnieje,private
a co nią jestprivate[this]
.źródło
private
tak, więc wpływ powinien wynosić zero lub co najmniej bardzo mały.Istnieje przypadek, w którym
private[this]
wymagane jest skompilowanie kodu. Ma to związek z interakcją notacji wariancji i zmiennych zmiennych. Rozważmy następującą (bezużyteczną) klasę:Tak więc ta klasa została zaprojektowana do przechowywania opcjonalnej wartości, zwracania jej jako opcji i umożliwienia użytkownikowi wywołania w
makeEmpty
celu wyczyszczenia wartości (stąd zmienna). Jak już wspomniano, jest to bezużyteczne, z wyjątkiem wykazania tego.Jeśli spróbujesz skompilować ten kod za pomocą
private
zamiastprivate[this]
niego, zakończy się niepowodzeniem i pojawi się następujący komunikat o błędzie:Ten błąd występuje, ponieważ value jest zmienną zmienną w kowariantnym typie T (+ T), co zwykle stanowi problem, chyba że jest oznaczona jako prywatna dla wystąpienia z
private[this]
. Kompilator ma specjalną obsługę sprawdzania wariancji, aby obsłużyć ten specjalny przypadek.Jest to więc ezoteryczne, ale jest przypadek, w którym
private[this]
jest to wymaganeprivate
.źródło
private var name
jest dostępny z dowolnej metodyclass Dummy
(i jego towarzyszącejobject Dummy
).private[this] var name
jest dostępny tylko z metodthis
obiektu, a nie z innych obiektówclass Dummy
.źródło
więc możesz zrobić to prywatnie za każdym razem, gdy chcesz, ale możesz mieć problem, jeśli będziesz potrzebować skierowania
źródło
private[this]
nie jest równeprotected[this]
.protected[this]
umożliwia instancjom podklasy dostęp do elementu członkowskiego.this.y == that.y
używać ani prywatnego, ani prywatnego [tego], właśnie wypróbowałem obaZostało to przetestowane przy użyciu wersji 2.11.5. Rozważ poniższy kod
skompiluje się i będzie działał jak ten kod java (1.8)
jednak jeśli użyjesz modyfikatora „[this]”, poniższy kod nie zostanie skompilowany
Dzieje się tak, ponieważ w pierwszym przypadku „x” jest dostępne na poziomie klasy, podczas gdy w drugim przypadku jest to bardziej rygorystyczny poziom instancji. Oznacza to, że dostęp do „x” można uzyskać tylko z instancji, do której należy. Więc „this.x” jest w porządku, ale „other.x” już nie.
Więcej informacji na temat modyfikatorów dostępu można znaleźć w sekcji 13.5 książki „Programming in Scala: A Comprehensive Step-by-Step Guide”.
źródło
private[this]
oznacza. Zwróć uwagę na pierwsze zdanie.Dodając zasięg do prywatnego modyfikatora ( private [X] ), efektywnie zachowuje się on jak „aż do” X, gdzie X wyznacza otaczający pakiet, klasę lub pojedynczy obiekt.
Na przykład private [bar] , gdzie bar jest pakietem, oznacza, że każda instancja każdej klasy należącej do paska pakietu ma dostęp do dowolnego elementu członkowskiego ograniczonego przez modyfikator.
W przypadku prywatnego [this] oznacza to, że członek jest dostępny tylko dla każdej instancji. Staje się to bardziej jasne w następującym przykładzie:
Jak widać, drugie Foo nie ma żadnego problemu, ponieważ każda instancja ma dostęp do prywatnej wartości. Jednak w przypadku pierwszego Foo występuje błąd, ponieważ każda instancja nie widzi i.
Dobrą praktyką jest pisanie tego na osobności, ponieważ nakłada to większe ograniczenie.
źródło
W większości języków programowania OOP, takich jak java, prywatne pola / metody oznaczają, że te prywatne pola / metody nie są dostępne poza klasą. Jednak instancje / obiekty tej samej klasy mogą mieć dostęp do prywatnych pól obiektów za pomocą operatora przypisania lub za pomocą konstruktora kopiującego. W Scali private [this] jest obiektem prywatnym, co zapewnia, że żaden inny obiekt tej samej klasy nie będzie mógł uzyskać dostępu do prywatnych elementów członkowskich [this].
Przykład
1.Bez prywatnego [this]
2.Używanie prywatnego [this]
Stąd private [this] zapewnia, że pole _password jest dostępne tylko z this.
źródło
Aby rozwinąć kwestię wydajności, o której wspomniał Aleksiej Romanow, oto niektóre z moich przypuszczeń. Cytaty z książki „Programming in Scala: A Comprehensive Step-by-Step Guide, 2nd Edition” Rozdział 18.2:
Aby to przetestować, ten kod spowoduje błąd kompilacji:
Scala narzeka
error: ambiguous reference to overloaded definition
. Dodanie słowa kluczowego override dodata_=
nie powinno pomóc w udowodnieniu, że metoda jest generowana przez kompilator. Dodanieprivate
słowa kluczowego do zmiennejdata
nadal spowoduje ten błąd kompilacji. Jednak poniższy kod kompiluje się dobrze:Myślę więc, że
private[this]
zapobiegnie generowaniu przez scala metod pobierających i ustawiających. Zatem dostęp do takiej zmiennej oszczędza narzut związany z wywołaniem metody pobierającej i ustawiającej.źródło
Lepiej jest użyć,
private[this]
jeśli planujesz zsynchronizować zmienną.Oto dobry przykład z przewodnika po stylu scala zespołu Spark :
źródło