w Scala, kiedy piszesz var foo
, kompilator Scala automatycznie generuje setter (tzw foo_=
) i getter (o nazwie foo
) i ustawia to pole jako prywatne (zobaczysz je jako prywatne, jeśli dekompilujesz klasę z "publicznymi" polami Scala z javap
). Tak właśnie oznacza błąd "method foo_ = overrides nothing". W swojej funkcji nie zdefiniowałeś metody foo_=
, a dla publicznego ustawiacza pól i pobierających zawsze są parami.
Jeśli nie podasz wartości domyślnej cechy (tj. Metody abstrakcyjnej), słowo kluczowe override
nie jest konieczne. Dlatego w twoim pierwszym przykładzie getter przesłania metodę abstrakcyjną i ustawiającą ... po prostu tam jest. Kompilator nie narzeka. Ale kiedy podajesz rzeczywistą implementację metody w tej cechie, podczas nadpisywania musisz konkretnie napisać słowo kluczowe override
. Podczas pisania protected var foo
nie podano słowa kluczowego dla programu pobierającego i podczas pisania override protected var foo
wskazano również kompilatorowi, że metoda foo_=
ma zostać nadpisana, ale cecha nie ma takiej metody.
Ponadto, logicznie rzecz biorąc, nie można naprawdę przesłonić wartości def
za pomocą var
(biorąc pod uwagę ścisły widok nadpisywania, jak w poprzednim akapicie). A def
jest logicznie funkcją (dajesz jej trochę wejścia, tworzy wyjście). A var
jest podobna do funkcji no-arg, ale obsługuje także ustawianie jej wartości na coś innego, operację, która nie jest obsługiwana przez funkcję. Zamiast tego, gdybyś zmienił go na val
, byłoby OK. To jest jak funkcja, która zawsze daje taki sam wynik (buforowany).
Jeśli chcesz mieć podobne zachowanie do var
można zrobić coś takiego (poprzez wyraźny setter i pobierające):
class Wibble extends SomeTrait {
private var bar = "Hello"
override protected def foo = bar
protected def foo_=(v: String) { bar = v}
}
teraz można zrobić niczego można zrobić z :) var.
val x = new Wibble
println(x.foo) // yields "Hello"
x.foo = "Hello again"
println(x.foo) // yields "Hello again"
Przepraszamy - popełniłem błąd - metoda pierwotnej cechy również powinna być chroniona. Nie jestem pewien, czy zgadzam się z tobą, że logicznie nie można zastąpić 'def' z' var'. Cała moja 'def' mówi, że oczekuję, że będzie jakiś accessor zwany' foo', który zwraca String - deklarowanie 'var' jest implementacją tego –
Myślę, że się z tobą zgadzam. Zastanawiałem się, czy nie nadpisać, jako bardziej rygorystycznego pojęcia, gdy pisałem odpowiedź. Zmienię odpowiedź i zapewni poprawne rozwiązanie :). –
Szkoda, że nie ma "nadpisania def jako składni var" –