Estaba trabajando en los ejemplos de código del capítulo sobre Rasgos en la programación en Scala Edition1 https://www.artima.com/pins1ed/traits.html
y me encontré con un comportamiento extraño debido a mi error tipográfico. Mientras se sobreescriben el método de un rasgo a continuación fragmento de código no da ningún error de compilación si bien los tipos de retorno del método reemplazado es diferente Unit
vs String
. Pero al llamar al método en un objeto, devuelve Unit pero no 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 = ()
Pero cuando doy el tipo de retorno explícito en el método anulado, da un error de compilación:
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
¿Alguien puede ayudar a explicar por qué no hay error de compilación en el primer caso?
scala
overriding
traits
Shanil
fuente
fuente
Respuestas:
Cuando el tipo esperado es
Unit
, cualquier valor puede ser aceptado :fuente
Cuando no especificó el tipo de retorno explícitamente, se infirió por el tipo que necesita tener para
override
que funcione.Eso resultó ser
Unit
.Como
String
se pueden asignar valores (el valor de la expresión que constituye el cuerpo de la función)Unit
, el compilador está contento.fuente
String
se rechazó el tipo de retorno explícito . En Java (y creo que también en Scala), se le permite limitar el tipo de retorno al anular. Por ejemplo, cuando el método padre regresaNumber
, usted puede regresarInteger
. Quizásvoid
/Unit
es especial.trait Philosophical { def philosophize : Number = 1 } class Frog extends Philosophical { override def philosophize : Integer = 2 }
String
toUnit
es más como el segundo, incluso si no es exactamente eso.Frog
:def philosophize : Integer
ydef philosophize : Number
. El segundo en realidad anula elPhilosophical
método (y llama al primero). Ciertamente, se podría hacer lo mismo porvoid
cualquier otra cosa, los diseñadores simplemente decidieron no hacerlo.