2012-04-17 16 views
6

¿Cómo puedo forzar que los métodos base tomen en la misma instancia de subclase específica cuando son reemplazados por una subclase?¿Reemplazando los métodos de subclase con argumentos subclase?

es decir .:

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

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

Lógicamente, un Cow sólo debe ser capaz de mateWith otra Cow. Sin embargo, si lo hago override def mateWith(that: Cow), esto en realidad no anula el método de la clase base (que yo quiero, ya que quiero imponer su existencia en la subclase).

Podría verificar para asegurarse de que la otra instancia sea de tipo Cow, y lanzar una excepción si no es - ¿esta es mi mejor opción? ¿Qué pasa si tengo más animales? Tendría que repetir el código de lanzamiento de excepción.

Respuesta

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

Y utilizar de esta manera:

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

Sin código de excepción de lanzamiento sea necesario; ¡el sistema de tipo lo maneja en tiempo de compilación!

+1

¡Encantador, Scala es conveniente como diablos! –

+1

No estoy tan seguro acerca de "conveniente", pero es expresivo. –

+1

Pensé en volver a visitar esto; esto se conoce como [f-acotado-polimorfismo] (https://twitter.github.io/scala_school/advanced-types.html#fbounded). –