scala – 为什么定义为“cons [B>:A](v:B)”的方法接受的类
我现在正在研究斯卡拉的变异,我认为我对逆变有很好的理解.例如给定特征列表[-A],我知道List [Int]是List [AnyVal]的超类型.
但是说我有以下特点: trait List[+A] { def cons(hd: A): List[A] } 为什么cons参数类型错误? 为什么有必要有缺点[B>:A](v:B):列出[B]? 例如: val animal_list: List[Animal] = List(tiger,dog) 如果我们打电话: animal_list.cons(tiger) 既然老虎< ;:动物,没有弊端?由于B是Tiger而A是Animal而B>:A不是真的. 解决方法
为什么cons的参数类型错误?
trait List[+A] { def cons(hd: A): List[A] } 编译器给你错误: 让我们假设这个方法声明会编译.然后我们可以这样做: class ListImpl[A] extends List[A] { override def cons(hd: A): List[A] = ??? } val strings: List[String] = new ListImpl[String] val values: List[Any] = strings // OK,since List[String] <: List[Any] (in List[A],A is covariant) values.cons(13) // OK(??),since values's static type is List[Any],so argument of cons should be Any,and 13 conforms to type Any 上面的最后一行真的好吗?我们在价值观上称之为利弊. values与字符串相同,字符串是ListImpl [String]类型的对象.因此,最后一行中的cons调用期望String参数,但我们传递Int,因为值的静态类型是List [Any],Int符合Any.这里肯定是错的 – 哪条线应该受到责备?答案是:cons方法声明.要解决这个问题,我们必须从逆变位置(在cons声明中)中删除协变类型参数A.或者,我们可以使A非协变. 另见这些问题:#1,#2. ……没有弊端? trait List[+A] { def cons[B >: A](v: B): List[B] } val animal_list: List[Animal] = List(tiger,dog) // We are assuming that List.apply and concrete implementation of List is somewhere defined. 不,animal_list.cons(tiger)调用是类型正确的. 我认为动物是狗和虎的常见超类型,而狗和虎分别是狗和虎的实例. 在animal_list.cons(tiger)调用中,A和B类型参数都被实例化为Animal,因此cons方法采用以下形式: def cons[Animal >: Animal](v: Animal): List[Animal] 动物>:满足动物约束,因为:
cons的论点是Tiger,它符合类型Animal,因此方法调用是类型正确的. 请注意,如果强制将B实例化为Tiger,例如animal_list.cons [Tiger](tiger),则此调用将不是类型正确的,并且您将收到编译器错误. 见类似的例子here. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |