Je travaillais sur les exemples de code du chapitre Traits in Programming in Scala Edition1 https://www.artima.com/pins1ed/traits.html
et est tombé sur un comportement étrange à cause de ma faute de frappe. Bien que la méthode de remplacement d'un trait sous l'extrait de code ne donne aucune erreur de compilation, bien que les types de retour de la méthode remplacée soient différents par Unit
rapport à String
. Mais en appelant la méthode sur un objet, elle renvoie Unit mais n'imprime rien.
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 = ()
Mais quand je donne le type de retour explicite dans la méthode surchargée, cela donne une erreur de compilation:
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
Quelqu'un peut-il aider à expliquer pourquoi aucune erreur de compilation dans le premier cas.
scala
overriding
traits
Shanil
la source
la source
Réponses:
Lorsque le type attendu est
Unit
, toute valeur peut être acceptée :la source
Lorsque vous n'avez pas spécifié explicitement le type de retour, cela a été déduit du type dont il a besoin pour que cela
override
fonctionne.Cela s'est avéré être
Unit
.Puisque des
String
valeurs (la valeur de l'expression constituant le corps de la fonction) peuvent être attribuéesUnit
, le compilateur est content.la source
String
été rejeté. En Java (et je pense aussi à Scala), vous êtes autorisé à restreindre le type de retour lors de la substitution. Par exemple, lorsque la méthode parent revientNumber
, vous pouvez retournerInteger
. Peutvoid
- être /Unit
est spécial.trait Philosophical { def philosophize : Number = 1 } class Frog extends Philosophical { override def philosophize : Integer = 2 }
String
toUnit
ressemble plus au second, même si ce n'est pas exactement ça.Frog
:def philosophize : Integer
etdef philosophize : Number
. La seconde remplace en fait laPhilosophical
méthode de (et appelle la première). La même chose pourrait certainement être faite pourvoid
/ n'importe quoi d'autre, les concepteurs ont juste décidé de ne pas le faire.