2012-04-17 9 views
6

Wie kann ich erzwingen, dass Basismethoden die gleiche spezifische Unterklasseninstanz übernehmen, wenn sie von einer Unterklasse überschrieben werden?Überschreiben von Unterklassenmethoden mit Unterklassenargumenten?

d.h .:

abstract class Animal { 
    def mateWith(that: Animal) 
} 

class Cow extends Animal { 
    override def mateWith...? 
} 

Logischerweise sollte ein Cow nur in der Lage sein, um mateWith andere Cow. Wenn ich jedoch override def mateWith(that: Cow) mache, überschreibt dies nicht tatsächlich die Basisklassenmethode (die ich will, da ich ihre Existenz in der Unterklasse erzwingen möchte).

Ich könnte überprüfen, um sicherzustellen, dass die andere Instanz vom Typ Kuh ist, und eine Ausnahme auslösen, wenn es nicht ist - ist das meine beste Option? Was ist, wenn ich mehr Tiere habe? Ich müsste den Ausnahme-Wurf-Code wiederholen.

Antwort

11
abstract class Animal[T <: Animal[T]] { 
    def mateWith(that: T) 
} 

class Cow extends Animal[Cow] { 
    override def mateWith(that: Cow) { println("cow") } 
} 

class Dog extends Animal[Dog] { 
    override def mateWith(that: Dog) { println("dog") } 
} 

Und es wie folgt verwenden:

scala> (new Cow).mateWith(new Cow) 
cow 

scala> (new Cow).mateWith(new Dog) 
<console>:17: error: type mismatch; 
found : Dog 
required: Cow 
       (new Cow).mateWith(new Dog) 
           ^

Keine Ausnahme werfenden Code erforderlich; das Typsystem handhabt es zur Kompilierzeit für Sie!

+1

Süßes Abkommen, Scala ist bequem wie heck! –

+1

Ich bin nicht so sicher über "bequem", aber ausdrucksvoll ist es. –

+1

Dachte, ich würde das noch einmal untersuchen - das nennt man [f-beschränkter Polymorphismus] (https://twitter.github.io/scala_school/advanced-types.html#fbounded). –