Eu estava trabalhando nos exemplos de código do capítulo Traits in Programming in Scala Edition1 https://www.artima.com/pins1ed/traits.html
e me deparei com um comportamento estranho por causa do meu erro de digitação. Enquanto substituindo método de um traço abaixo trecho de código não dá qualquer erro de compilação, embora os tipos de retorno do método substituído é diferente Unit
vs String
. Mas, ao chamar o método em um objeto, ele retorna Unit, mas não imprime nada.
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 = ()
Mas quando eu dou o tipo de retorno explícito no método substituído, ele gera um erro de compilação:
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
Alguém pode ajudar a explicar por que nenhum erro de compilação no primeiro caso.
scala
overriding
traits
Shanil
fonte
fonte
Respostas:
Quando o tipo esperado é
Unit
, qualquer valor pode ser aceito :fonte
Quando você não especificou o tipo de retorno explicitamente, foi inferido pelo tipo que ele precisa ter para que o
override
trabalho funcione.Isso acabou por ser
Unit
.Como
String
valores (o valor da expressão que compõe o corpo da função) podem ser atribuídosUnit
, o compilador fica feliz.fonte
String
foi rejeitado. Em Java (e também penso em Scala), você pode restringir o tipo de retorno ao substituir. Por exemplo, quando o método pai retornarNumber
, você poderá retornarInteger
. Talvezvoid
/Unit
seja especial.trait Philosophical { def philosophize : Number = 1 } class Frog extends Philosophical { override def philosophize : Integer = 2 }
String
toUnit
é mais parecido com o segundo, mesmo que não seja exatamente isso.Frog
:def philosophize : Integer
edef philosophize : Number
. O segundo substitui oPhilosophical
método do (e chama o primeiro). O mesmo certamente poderia ser feito paravoid
/ qualquer outra coisa, os designers simplesmente decidiram não fazê-lo.