Este es un patrón que se utiliza a menudo para que una clase abstracta sepa el tipo de la clase real de hormigón que lo extiende. A veces es útil saber cuál es el tipo concreto final: por ejemplo, usarlo como el tipo de devolución de un método que produce una copia del objeto actual.
Supongamos que quiere hacer esto: deje que una clase abstracta Abstract
conozca el tipo concreto que lo implementa. Se podría empezar por definir un parámetro de tipo, tal como esto:
trait Abstract[A] {
def copyObject: A = ...
}
Pero luego te das cuenta de que en realidad, A
debe ser una subclase de Abstract
en sí, ya que no quiere subclases para proporcionar una parametrización al azar. Por lo que podría añadir lo siguiente:
trait Abstract[A <: Abstract]
... pero pronto se dará cuenta de que Abstract
se ha convertido en un tipo genérico, así, por lo que más bien necesita esto:
trait Abstract[A <: Abstract[A]]
Como paso final, es probable que quieren hacer A
covariante si es posible, con el fin de permitir que las clases abstractas intermedios a lo largo de la ruta de herencia de Abstract
a la clase final de hormigón:
trait Abstract[+A <: Abstract[A]]
class Concrete1 extends Abstract[Concrete1]
trait RefinedAbstract[+A <: RefinedAbstract[A]] extends Abstract[A]
class Concrete2 extends RefinedAbstract[Concrete2]
Esto significa que cada tipo no hoja (abstracto) debe parametrizarse, y que solo la clase concreta final podrá soltar el parámetro tipo.
Tenga en cuenta que lo mismo es posible y realmente hecho en Java o C#. por ejemplo, SortedStructure> ', SortedStructure donde T: IComparable '. –