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

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] 的隐式参数。

基本上来说:

  • 我想临时创建一个新的匿名类/实例 (例如 new Foo[Int] { ... } ), 并将其传递给一个"add"方法,此方法将其添加到列表中,然后返回它
  • 关键在于来自 "val foo = " 的变量, 我希望它的 类型 是匿名类,而不是Foo[Int],因为它添加了方法
    (在这个例子中是someMethod)

有什么想法吗?

我认为第二个代码段失败是因为类型Int被擦除了。我可以通过这样的'提示'让编译器正常工作: (这个方法可行, 但似乎有点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
  }

1
很好,听起来不错 :) 希望它很快发布! - waterlooalex
你的错误提示存在协变问题(尽管 X 本应 没有被推导为 Nothing)... 试过使用 class Foo[+T] 吗? - Dario
可以,谢谢。但是这破坏了我的其他代码。类Foo[+T] { var _val: Option[T] } 无法编译。“协变类型T出现在值_val的逆变位置上的类型Option[T]中” - waterlooalex
这只是2.7.7版本中的一个bug吗? - waterlooalex
1个回答

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
  }

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接