2011-07-29 11 views
6

Estoy buscando una forma de definir un método que devuelva un tipo T donde T = el tipo de la subclase.Tipo abstracto de Scala que representa el tipo de subclase

Sé que podría hacer esto usando tipos abstractos, pero no me gusta la sobrecarga de tener que redefinir T para cada subclase.

un código de ejemplo:

object Helper { 
    def help[A <: MyClass](cls: A): Option[A] = { cls.foo() map { _.asInstanceOf[A] } } 
} 

class MyClass { 
    type T <: MyClass 
    def foo(): Option[T] = Some(this.asInstanceOf[T]) 
} 

class ChildClass extends MyClass { 
    type T = ChildClass 
} 

Posiblemente una nueva característica del lenguaje ha hecho esto más fácil? ¿O puedo usar this.type de alguna manera? Para mí es importante poder definir una clase de ayuda que pueda llamar a foo de esta manera.

Respuesta

3

Si siempre devuelve this, puede tener como tipo de devolución this.type. ¿O lo has probado ya?

this.type es especialmente útil, p. cuando desee encadenar llamadas al mismo objeto o proporcionar una garantía estática de que devolverá el mismo objeto (y no una copia). Por ejemplo, Buffer s en Scala tienen la operación de agregar :+, que devuelve Buffer[A], y +=, que devuelve this.type. El primero duplica la secuencia mutable; este último le garantiza que actualice el objeto original.

+1

Hay alguna posibilidad me puede indicar alguna sintaxis específica que funcionaría dado que necesito escribir Helper.help exactamente como está (con el parámetro tipo)? this.type no coincide con A? Además, tenga en cuenta que debo devolver Option [this.type] y def foo: Option [this.type] = Some (this) no parece compilarse. ¡Gracias por tu ayuda! –

+1

@Pandora Los tipos de Singleton nunca se deducen, debe especificarlo explícitamente: 'Some [this.type] (this)'. –

+0

¡Muchas gracias! Me encontré con otro problema ya que mi función foo en la práctica llama al método estático de otro objeto -> pregunta de seguimiento aquí si tiene ideas :) http://stackoverflow.com/questions/6886182/scala-this- type-conformity-to-type-parameter-bounds-of-supertype –

2

Para dar seguimiento a la respuesta de Jean-Phillippe, que escribió su exactamente cuando estoy escribiendo el mío, aquí está el código:

trait SomeTrait { 
    def foo: this.type = this 
} 

class UsesTrait extends SomeTrait 

object Main { 
    def main(args: Array[String]) { 
    println((new UsesTrait).foo) // prints [email protected]<hash value> 
    } 
} 
+0

Genial, esto es útil. ¿Esto se extiende a Option [this.type]? def foo: Option [this.type] = Algunos (esto) no parecen compilarse. –

+0

Je, finalmente terminé con esto también. Esta es una de las características del lenguaje menos documentadas teniendo en cuenta la importancia que tiene ... – lisak

2

me encontré con la siguiente expresión idiomática útil:

class MyClass[T] { 
    self: T => 
    def foo(): Option[T] = Some(this) 
} 

class ChildClass extends MyClass[ChildClass] 

new ChildClass().foo() 
//--> Option[ChildClass] = Some([email protected]) 
+0

Sí, pero: • tiene que ser un rasgo si se quiere permitir una jerarquía completa de clases, y • debe ser covariante en ' T'. En general, más restricciones que un simple 'this.type', ¿no? –

+0

@ Jean-Philippe Pellet: Sí, parece. Estoy meditando sobre si puede tener también ventajas, pero no encontré ninguna. – Landei

Cuestiones relacionadas