¿Tiene sentido una clase con un tipo propio de otra clase?

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 propio en clase A, por lo tanto clase B (o una subclase de ella) tiene que extender la clase A para crear una instancia de B. Pero, ¿es esto posible en absoluto, ya que una subclase de B solo puede extender una clase (y esta es la clase B)?

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

preguntado el 30 de junio de 12 a las 13:06

1 Respuestas

Tiene razón con la observación de que esta definición no puede conducir a una implementación concreta, ya que no se pueden mezclar dos clases, solo rasgos. Entonces, la respuesta corta es 'no', cualquiera de los dos debería ser un rasgo.

Hay varias preguntas sobre Stackoverflow con respecto a los tipos propios. Dos útiles son estos:

En la segunda pregunta, hay una buena respuesta de Ben Lings quien cita el siguiente pasaje del blog de Spiros Tzavellas:

En conclusión, si queremos mover las implementaciones de métodos dentro de las características, corremos el riesgo de contaminar la interfaz de esas características con métodos abstractos que respaldan la implementación de los métodos concretos y no están relacionados con la responsabilidad principal de la característica. 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 (¡Supongamos que ahora es un rasgo y no una clase!) es un registrador. No quieres exponer para B públicamente la API de registro mezclada por A. Por lo tanto, usaría un tipo propio y no una mezcla. Dentro de la implementación de B puede llamar a la API de registro, pero desde el exterior no es visible.


Por otro lado, podrías usar la composición de la siguiente forma:

trait B {
    protected def logger: A
}

La diferencia ahora es que

  • B debe referirse a logger al querer usar su funcionalidad
  • subtipos de B tener acceso al logger
  • B y A no compita en el espacio de nombres (por ejemplo, podría tener métodos del mismo nombre sin colisión)

Diría que los autotipos son una característica bastante periférica de Scala, no los necesita en muchos casos, y tiene opciones como esta para lograr casi lo mismo sin autotipos.

contestado el 23 de mayo de 17 a las 13:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.