io non sono sicuro se c'è un modo migliore di fare questo:Problema "MyType": Devo usare tipi astratti (o generici) in Scala per restituire la classe effettiva?
trait Animal {
val name: String
val weight: Int
type SubAnimal <: Animal
def updateName(n: String) = returnMe(n, this.weight)
def updateWeight(w: Int) = returnMe(this.name, w)
// Abstract protected method
protected def returnMe(n: String, w: Int): SubAnimal
}
case class Dog(name: String, weight: Int) extends Animal {
type SubAnimal = Dog
override def returnMe(n: String, w: Int): Dog = Dog("Dog: " + name, w)
}
case class Cat(name: String, weight: Int) extends Animal {
type SubAnimal = Cat
override def returnMe(n: String, w: Int): Cat = Cat("Cat: " + name, w)
}
val fido = Dog("Fido", 11)
println(fido)
val fido2 = fido.updateWeight(12)
println(fido2)
Quando eseguo il codice ottengo questo output:
$ scala animal.scala
Dog(Fido,11)
Dog(Dog: Fido,12)
voglio restituire il tipo effettivo dell'animale in questione dopo che è stato chiamato il updateName
o updateWeight
(ovvero non Animal
). So che se si esegue l'override direttamente su updateName
e updateWeight
, verrà restituito il tipo corretto e non è necessario utilizzare il tipo astratto SubAnimal
.
Esiste qualche modo complicato di sfuggire al tipo astratto per il caso speciale in cui il valore del tipo astratto è lo uguale alla sottoclasse?
(questo è noto come problema "MyType").
Quindi il modo magico sarebbe usare "this.type" (dal tuo link) ma dal momento che sto restituendo una nuova istanza (non questa), allora non è possibile. Più avanti nel post Odersky raccomanda i tipi astratti per questo problema, quindi immagino che termini la discussione. Grazie. –
Sì, questo tipo è troppo stretto per agire come MyType: è il tipo di questo * ma nessun'altra istanza di questa classe *. –