2010-05-11 12 views
9

Tengo este código que funciona:Cómo llamar a un método genérico con un tipo anónimo que involucra genéricos?

def testTypeSpecialization: String = { 
    class Foo[T] 

    def add[T](obj: Foo[T]): Foo[T] = obj 

    def addInt[X <% Foo[Int]](obj: X): X = { 
     add(obj) 
     obj 
    } 

    val foo = addInt(new Foo[Int] { 
     def someMethod: String = "Hello world" 
    }) 

    foo.someMethod 
    } 

Pero, me gustaría escribir así:

def testTypeSpecialization: String = { 
    class Foo[T] 

    def add[X, T <% Foo[X](obj: T): T = obj 

    val foo = add(new Foo[Int] { 
     def someMethod: String = "Hello world" 
    }) 

    foo.someMethod 
    } 

Esta segunda falla al compilar:

sin se ha encontrado el tipo de parámetro de concordancia de argumento implícito (Foo [Int] {...}) => Foo [Nothing].

Básicamente:

  • Me gustaría crear una nueva clase /instancia anónima sobre la marcha (por ejemplo, nueva Foo [Int] {...}), y pasarlo a un "add" método que añadirlo a una lista , y luego devolverlo
  • la clave aquí es que la variable de "foo val =" me gustaría
    su tipo a ser la clase anónima , no Foo [Int], ya que añade métodos
    (algunMetodo en este ejemplo)

alguna idea?

Creo que la segunda falla porque se borra el tipo Int. Que pueda parecer 'toque' el compilador de la siguiente manera: (esto funciona, pero parece como un hack)

def testTypeSpecialization = { 
    class Foo[T] 

    def add[X, T <% Foo[X]](dummy: X, obj: T): T = obj 

    val foo = add(2, new Foo[Int] { 
     def someMethod: String = "Hello world" 
    }) 

    foo.someMethod 
    } 
+0

funciona bien bajo Scala 2,8! – Dario

+1

Bueno, eso es bueno escuchar :) ¡ojalá se publique pronto! –

+0

Tu error sugiere un problema de covarianza (Aunque 'X' * nunca debería haber sido deducido a' Nada') ... Intentó 'clase Foo [+ T]'? – Dario

Respuesta

1

Darío sugirió hacer T covariante en Foo:

def testTypeSpecialization: String = { 
    class Foo[+T] { 
     var _val: Option[T] 
    } 

    def add[X, T <% Foo[X](obj: T): T = obj 

    val foo = add(new Foo[Int] { 
     def someMethod: String = "Hello world" 
    }) 

    foo.someMethod 
    } 

Pero, con esto se suma demasiados restricciones a Foo parece, por ejemplo No puedo tener una variable miembro var de tipo Opción [T].

tipo covariante T se produce en la posición contravariant en el tipo Opción [T] de parámetro de setter val =

Cuestiones relacionadas