泛型类方法调用的类型不匹配

时间:2017-05-18 22:14:45

标签: scala

请考虑以下简单示例:

class C[P](val list: Seq[P]){
  def print(e: P){
    println(e)
  }
}

object Test{
  def g[P](c: C[P]) = {
    c.print(c.list(0))
  }

  def f(i: Int): C[_] = {
    i match {
      case 1 => new C(Seq(1, 2, 3))
      case _ => new C(Seq("A", "B", "C"))
    }
  }

  def main(args: Array[String]): Unit = {
    val c = f(1)
    g(c) // works
    c.print(c.list(0)) // does not work
  }
}

我的问题是,在主函数中,为什么第一个调用编译,但第二个调用"类型不匹配"错误。

还有其他(更好)的方式来做这里的目的吗?

修改1

根据@chengpohi的回答,我可以将f的返回值的类型更改为C[Any],但这通常可能无效。例如,如果我们将代码更改为

class B[P]

class BInt extends B[Int]

class BString extends B[String]

class C[P](val list: Seq[P], val obj: B[P]) {
  def print(e: P) {
    println(e)
  }
}

object Test {
  def g[P](c: C[P]) = {
    c.print(c.list(0))
  }

  def f(i: Int): C[_] = {
    i match {
      case 1 => new C(Seq(1), new BInt)
      case _ => new C(Seq("String"), new BString)
    }
  }

  def main(args: Array[String]): Unit = {
    val c = f(1)
    g(c) // works
    c.print(c.list(0)) // does not work
  }
}

我无法再将f的返回类型更改为C[Any]("类型不匹配")。

2 个答案:

答案 0 :(得分:1)

  def f(i: Int): C[Any] = {
    i match {
      case 1 => new C(Seq(1, 2, 3))
      case _ => new C(Seq("A", "B", "C"))
    }
  }

尝试从f设置C[Any]方法返回类型:C[_],对于类型C[_],编译器会将C[_]翻译为C<?> }。

有:

  def g[P](c: C[P]) = {
    c.print(c.list(0))
  }

此方法有效,这是由于我们在此方法P中绑定了g类型,因此编译器可以推断出此通用PObject类型)

但主要方法是:

c.print(c.list(0))

c没有类型上下文,c的类型为C[_],但c.list的类型为Seq[Any],而通用类型{ P中的{1}}将被视为c.print类型。所以抛出了_$1编译错误。

答案 1 :(得分:0)

您可以使用类型变量模式为type参数指定名称:

f(1) match {
  case c: C[a] => c.print(c.list(0))
}