2012-04-17 3 views
6

Come posso forzare i metodi di base a prendere nella stessa istanza di sottoclasse specifica quando sovrascritta da una sottoclasse?Sovrascrivere i metodi di sottoclasse con argomenti sottoclassi?

cioè .:

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

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

Logicamente, un Cow dovrebbe essere solo in grado di mateWith un'altra Cow. Tuttavia, se faccio override def mateWith(that: Cow), questo in realtà non sovrascrive il metodo della classe base (che io voglio, dal momento che voglio far valere la sua esistenza nella sottoclasse).

Potrei verificare che l'altra istanza sia di tipo Cow e lanciare un'eccezione se non lo è - questa è la mia migliore opzione? Cosa succede se ho più animali? Dovrei ripetere il codice di lancio delle eccezioni.

risposta

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") } 
} 

e usarlo in questo modo:

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) 
           ^

Nessun codice di eccezione-lancio necessaria; il sistema di tipi lo gestisce per te in fase di compilazione!

+1

Dolce accordo, la Scala è comoda come diamine! –

+1

Non sono così sicuro di "conveniente", ma è espressivo. –

+1

Ho pensato di rivisitare questo - questo è noto come [polimorfismo delimitato da f] (https://twitter.github.io/scala_school/advanced-types.html#fbounded). –