请考虑以下简单示例:
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]
("类型不匹配")。
答案 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
类型,因此编译器可以推断出此通用P
(Object
类型)
但主要方法是:
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))
}