2010-04-07 19 views
8

En Scala v 2.7.7Scala parámetros de tipo paso a objeto

Tengo un archivo con

class Something[T] extends Other 

object Something extends OtherConstructor[Something] 

Esto arroja el error:

class Something takes type parameters
object Something extends OtherConstructor[Something] {

Sin embargo, no puedo hacer

object Something[T] extends OtherConstructor[Something[T]] 

Se lanza un error:

error: ';' expected but '[' found.

¿Es posible enviar parámetros de tipo a un objeto? O debería cambiar y simplemente usar Otherconstructor

Respuesta

3

Un objeto debe tener un tipo concreto. La construcción del objeto Scala no es una excepción a esta regla.

Una definición válida es

object Something extends OtherConstructor[Something[T]] { } 

donde T es un poco de concreto Tipo.

4

que puede usar:

object Something extends OtherConstructor[Something[_]] 

Usted, por supuesto estar restringido por tener un tipo existencial sin límite superior en su lugar en vez de un tipo concreto. Esta solución puede no tener sentido y es posible que necesite un objeto por tipo concreto T, para esas "T" que le interesan, p.

object StringSomething extends OtherConstructor[Something[String]] 

Pero entonces esto tiene el (posible) StringSomething desventaja de que no es el objeto acompañante de Something.

Sin embargo, mi consejo sería no empiece a perder el diseño de APIs genéricos (especialmente autorreferenciales como el de arriba) a menos que realmente, realmente sabe lo que está haciendo. Es casi seguro que terminará en lágrimas y hay un montón de Core Java API de los cuales son terribles debido a la forma en que se han añadido los genéricos (el RowSorter API en JTable siendo un ejemplo)

+0

El API APT es agradable también: 'List \t getAnnotationMirrors() '(http://java.sun.com/javase/6/docs/api/javax/lang/model/element/Element.html#getAnnotationMirrors%28%29) ;-) –

1

Gracias por las respuestas

object Something extends OtherConstructor[Something[_]] 

parece estar compilación (aunque todavía tengo que ejecutar/probar que :-))

@oxbow_lakes, he seguido su consejo - de evitar el sistema de tipos - hasta ahora pero tengo que hacerlo !!! He estado estudiando los tipos existenciales, tipo de borrado y todo eso, pero su todavía no está en mi mano :-(

1

Puede resolver el problema general de la necesidad object Foo[T] moviendo el tipo de parámetro a los métodos de object Foo:

class Foo[T](t1: T, t2: T) 

object Foo { 
    def apply[T](x: T): Foo[T] = new Foo(x, x) 
    def apply[T](x: T, y: T): Foo[T] = new Foo(x, y) 
} 

Si realmente necesita un objeto por T, se puede hacer una clase, y tienen el compañero libre de tipo volverlo a partir de aplicar.

class Foo[T](t1: T, t2: T) 

class FooCompanion[T] { 
    def apply(x: T): Foo[T] = new Foo(x, x) 
    def apply(x: T, y: T): Foo[T] = new Foo(x, y) 
} 

object Foo { 
    def apply[T] = new FooCompanion[T] 
} 

object demo extends App { 
    val x: Foo[Double] = Foo.apply.apply(1.23) // this is what is really happening 
    val y: Foo[Int] = Foo[Int](123)    // with the type both apply calls are automatic 
} 

Nota esto será re-construir el Foo [T ] compañero en cada llamada, por lo que querrá mantenerlo ligero y sin estado.

una solución explícita del problema anterior:

class Other 

class OtherConstructor[O <: Other] { 
    def apply(o: O): O = o // constructor 1 in base class 
} 

class Something[T](value: T) extends Other 

class SomethingConstructor[T] extends OtherConstructor[Something[T]] { 
    def apply(o: T, s: String) = new Something[T](o) // constructor 2 in subclass 
} 

object Something { 
    def apply[T] = new SomethingConstructor[T] // the "constructor constructor" method 
} 

object demoX extends App { 
    val si = new Something(123) 
    val sd = new Something(1.23) 

    val si1: Something[Int] = Something[Int](si)     // OtherConstructor.apply 
    val sd1: Something[Double] = Something[Double](1.23, "hello") // SomethingConstructor[Double].apply 
} 
Cuestiones relacionadas