2012-06-30 4 views
6
scala> class A 
defined class A 

scala> class B {this: A => } 
defined class B 

scala> new B 
<console>:10: error: class B cannot be instantiated because it does not conform 
to its self-type B with A 
      new B 
      ^

Clase B establece el tipo de auto a clase A, por lo tanto clase B (o una subclase de la misma) tiene que extender clase A para crear una instancia de B. Pero, ¿esto es posible en absoluto, ya que una subclase de B solo puede extender una clase (y esta es la clase B)?¿Tiene sentido una clase con un tipo propio de otra clase?

Así que esto me lleva a la pregunta, ¿tiene sentido declarar el tipo de una clase a otra clase en cualquier caso?

Respuesta

10

Tiene razón con la observación de que esta definición no puede conducir a una implementación concreta, ya que no puede mezclar dos clases, solo rasgos. Entonces la respuesta corta es 'no', o bien debe ser un rasgo.

Hay varias preguntas sobre Stackoverflow con respecto a los tipos propios. Dos de las más útiles son los siguientes:

En la segunda cuestión, no es una buena respuesta por Ben Lings que cita el siguiente pasaje de blog de Spiros Tzavellas:

En conclusión, si queremos mover las implementaciones de métodos dentro de los rasgos, corremos el riesgo de contaminar la interfaz de esos rasgos con métodos abstractos. apoyar la implementación de los métodos concretos y no están relacionados con la responsabilidad principal del rasgo. Una solución a este problema es mover esos métodos abstractos en otros rasgos y componer los rasgos juntos usando anotaciones de tipo propio y herencia múltiple.

Por ejemplo, si A (suponiendo que se trata de un rasgo y no una clase ahora!) Es un registrador. No desea exponer para B públicamente la API de registro mezclada por A. Por lo tanto, usarías un tipo propio y no mixin. Dentro de la implementación de B puede llamar a la API de registro, pero desde el exterior no está visible.


Por otra parte, se puede utilizar la composición de la siguiente forma:

trait B { 
    protected def logger: A 
} 

La diferencia ahora es que

  • B hay que referirse a logger al querer utilizar su funcionalidad
  • subtipos de B tienen acceso a logger
  • B y A no compiten en el espacio de nombres (p. podría tener métodos con el mismo nombre sin colisión)

Yo diría que la auto-tipos son una característica bastante periférica de Scala, que no los necesita en muchos casos, y usted tiene opciones como ésta para alcanzar casi lo mismo sin auto-tipos.

+0

Gran respuesta, muchas gracias. –

Cuestiones relacionadas