2010-05-11 2 views
9

У меня есть этот код, который работает:Как вызвать общий метод с анонимным типом с использованием дженериков?

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 
    } 

Но, я хотел бы написать это следующим образом:

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 
    } 

Это второй один не может скомпилировать:

нет неявный аргумент типа параметра (Foo [Int] {...}) => Foo [Nothing].

В основном:

  • Я хотел бы создать новый анонимный класс/экземпляр на лету (например, новый Foo [Int] {...}), и передать его в в «добавить» метод, который добавит его список, а затем вернуть его
  • ключевым моментом здесь является то, что переменная от «валь Foo =» Я хотел бы
    его типа быть анонимный класс , не Foo [Int], так как он добавляет методы
    (SomeMethod в данном примере)

Любые идеи?

Я думаю, что второй из них терпит неудачу, потому что тип Int стирается. Я могу по-видимому, «намек» компилятор так: (это работает, но, кажется, как взломать)

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

отлично работают под Скале 2.8! – Dario

+1

Хорошо, это приятно слышать :) надеюсь, скоро он выйдет! –

+0

Ваша ошибка подсказывает проблему ковариации (хотя 'X' * should * никогда не был выведен на' Nothing') ... Пробовал 'class Foo [+ T]'? – Dario

ответ

1

Дарио предложил сделать T коварианты в 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 
    } 

Но, с этим добавляет слишком много ограничений на Foo кажется, например Я не могу иметь переменную-член переменной типа Option [T].

ковариантный типа Т происходит в контравариантной позиции в типе Option [T] от параметра инкубаторе вал =

Смежные вопросы