如何使用涉及泛型的匿名类型调用泛型方法?

Ale*_*ack 9 generics scala type-inference

我有这个代码有效:

  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
  }
Run Code Online (Sandbox Code Playgroud)

但是,我想这样写:

 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
  }
Run Code Online (Sandbox Code Playgroud)

第二个无法编译:

没有隐式参数匹配参数类型(Foo [Int] {...})=> Foo [Nothing]被找到.

基本上:

  • 我想动态创建一个新的匿名类/实例(例如new Foo [Int] {...}),并将其传递给"add"方法,该方法将其添加到列表中,然后将其返回
  • 这里的关键是来自"val 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
  }
Run Code Online (Sandbox Code Playgroud)

Ale*_*ack 1

Dario 建议在 Foo 中使 T 协变:

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
  }
Run Code Online (Sandbox Code Playgroud)

但是,这似乎给 Foo 添加了太多限制,例如我不能拥有 Option[T] 类型的 var 成员变量。

协变类型 T 出现在 setter val =参数的类型 Option[T] 中的逆变位置