Pracowałem nad przykładami kodu z rozdziału dotyczącego cech w programowaniu w Scala Edition1 https://www.artima.com/pins1ed/traits.html
i natknąłem się na dziwne zachowanie z powodu mojej literówki. Podczas gdy metoda przesłaniania cechy poniżej fragmentu kodu nie daje żadnego błędu kompilacji, chociaż typy zwracane przez przesłoniętą metodę są inne Unit
niż String
. Ale po wywołaniu metody na obiekcie zwraca Unit, ale nic nie drukuje.
trait Philosophical {
def philosophize = println("I consume memory, therefore I am!")
}
class Frog extends Philosophical {
override def toString = "green"
override def philosophize = "It aint easy to be " + toString + "!"
}
val frog = new Frog
//frog: Frog = green
frog.philosophize
// no message printed on console
val f = frog.philosophize
//f: Unit = ()
Ale gdy podaję jawny typ zwrotu w przesłoniętej metodzie, pojawia się błąd kompilacji:
class Frog extends Philosophical {
override def toString = "green"
override def philosophize: String = "It aint easy to be " + toString + "!"
}
override def philosophize: String = "It aint easy to be " + toString +
^
On line 3: error: incompatible type in overriding
def philosophize: Unit (defined in trait Philosophical);
found : => String
required: => Unit
Czy ktoś może wyjaśnić, dlaczego w pierwszym przypadku nie wystąpił błąd kompilacji.
scala
overriding
traits
Shanil
źródło
źródło
Odpowiedzi:
Gdy oczekiwanym typem jest
Unit
, można zaakceptować dowolną wartość :źródło
Jeśli nie określono wyraźnie typu zwrotu, został on wywnioskowany na podstawie typu, jaki musi on mieć
override
do działania.Okazało się, że tak
Unit
.Ponieważ
String
można przypisać wartości (wartość wyrażenia tworzącego ciało funkcji)Unit
, kompilator jest szczęśliwy.źródło
String
został odrzucony. W Javie (i myślę również w Scali) możesz zawęzić typ zwracany podczas przesłonięcia. Na przykład po powrocie metody nadrzędnejNumber
możesz zwrócićInteger
. Możevoid
/Unit
jest wyjątkowy.trait Philosophical { def philosophize : Number = 1 } class Frog extends Philosophical { override def philosophize : Integer = 2 }
String
doUnit
bardziej jakby drugim, nawet jeśli nie jest to dokładnie to.Frog
:def philosophize : Integer
idef philosophize : Number
. Drugi faktycznie zastępujePhilosophical
metodę (i wywołuje pierwszą). To samo można z pewnością zrobić dlavoid
/ czegokolwiek innego, projektanci po prostu postanowili tego nie robić.