trait Account[T <: Account[T]]
case class BrokerAccount(total:BigDecimal) extends Account[BrokerAccount]
case class SavingsAccount(total:BigDecimal) extends Account[SavingsAccount]
下面的函数声明和调用工作正常。
def foo1( xs: Array[T forSome { type T <: Account[T] }]):Array[T forSome { type T <: Account[T] }] = xs
foo1(Array(BrokerAccount(100),SavingsAccount(50)))
但是下面的调用会产生编译错误。
def foo2( xs: List[T forSome { type T <: Account[T] }]):List[T forSome { type T <: Account[T] }] = xs
foo2(List(BrokerAccount(100),SavingsAccount(50)))
错误
Main.scala:14:错误:类型不匹配;
找到:列出[具有Serializable with Main.Account的产品[_&gt ;: Main.SavingsAccount与Main.BrokerAccount&lt ;: Product with Serializable with Main.Account [_&gt ;: Main.SavingsAccount with Main.BrokerAccount&lt ;: Product with Serializable接口]]]
required:List [T forSome {type T&lt;:Main.Account [T]}] foo2(List(BrokerAccount(100),SavingsAccount(50)))
有人可以解释一下为什么在以后的情况下会发生编译错误吗?
答案 0 :(得分:3)
问题的关键是方差 - 你试图在协变位置(函数返回类型)返回逆变值。
尽管List
类型在其参数(trait List[+A]
)中是协变的,但这实质上意味着它的值是逆变的(可以分配给超类型列表):
val listOfSupers: List[_ >: Account[_]] = List(BrokerAccount(100), SavingsAccount(50))
您尝试从函数foo2
返回的内容完全相反 - List[_ <: Account[_]]
,因此编译错误。
如果您使用List
代替Set
而不是Array
,那么它的类型参数就像int length = Math.min(arrayA.length, arrayB.length);
for (int i = 0; i < length; i++) {
一样不变,一切都会正常工作。