简体   繁体   English

Scala F界类型多态性

[英]Scala F-Bounded Type Polymorphism

trait Account[T <: Account[T]]

case class BrokerAccount(total:BigDecimal) extends Account[BrokerAccount]
case class SavingsAccount(total:BigDecimal) extends Account[SavingsAccount]

Below function declaration and invocation works fine. 下面的函数声明和调用工作正常。

def foo1( xs: Array[T forSome { type T <: Account[T] }]):Array[T forSome { type T <: Account[T] }] = xs
foo1(Array(BrokerAccount(100),SavingsAccount(50)))

But below invocation gives compilation error. 但是下面的调用给出了编译错误。

def foo2( xs: List[T forSome { type T <: Account[T] }]):List[T forSome { type T <: Account[T] }] = xs
foo2(List(BrokerAccount(100),SavingsAccount(50)))

Error 错误

Main.scala:14: error: type mismatch; Main.scala:14:错误:类型不匹配;
found : List[Product with Serializable with Main.Account[_ >: Main.SavingsAccount with Main.BrokerAccount <: Product with Serializable with Main.Account[_ >: Main.SavingsAccount with Main.BrokerAccount <: Product with Serializable]]] 找到:列表[具有Main.Account可序列化的产品[_>:具有Main.BrokerAccount的Main.SavingsAccount <_:具有Main.BrokerAccount的具有序列化的产品[_>:具有Main.BrokerAccount <可具有序列化的产品]]]]
required: List[T forSome { type T <: Main.Account[T] }] foo2(List(BrokerAccount(100),SavingsAccount(50))) 必需:List [T forSome {类型T <:Main.Account [T]}] foo2(List(BrokerAccount(100),SavingsAccount(50)))

Can someone please explain me why compilation error occur in later case? 有人可以解释一下为什么以后会出现编译错误吗?

The key to the problem is variance - you're trying to return a contravariant value in covariant position (function return type). 问题的关键是方差-您正在尝试在协变位置(函数返回类型)中返回一个对数值。 Despite List type is covariant in its argument ( trait List[+A] ), this essentially means its values are contravariant (can be assigned to a List of supertypes): 尽管List类型在其参数中是协变的( trait List[+A] ),但这实际上意味着其值是协变的(可以分配给超类型的List):

val listOfSupers: List[_ >: Account[_]] = List(BrokerAccount(100), SavingsAccount(50))

What you're trying to return from the function foo2 is a complete contrary - List[_ <: Account[_]] , thus the compiler error. 您试图从函数foo2返回的是一个完全相反的结果foo2 List[_ <: Account[_]] ,因此是编译器错误。

If instead of List you use Set there, which is invariant in its type parameter just like Array , everything will work fine. 如果使用Set代替List而不使用List ,则Set的类型参数不变,就像Array一样,一切都会正常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM