加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 为什么定义为“cons [B>:A](v:B)”的方法接受的类

发布时间:2020-12-16 18:08:36 所属栏目:安全 来源:网络整理
导读:我现在正在研究斯卡拉的变异,我认为我对逆变有很好的理解.例如给定特征列表[-A],我知道List [Int]是List [AnyVal]的超类型. 但是说我有以下特点: trait List[+A] { def cons(hd: A): List[A]} 为什么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)

既然老虎&lt ;:动物,没有弊端?由于B是Tiger而A是Animal而B>:A不是真的.

解决方法

为什么cons的参数类型错误?

trait List[+A] {
  def cons(hd: A): List[A]
}

编译器给你错误:
协变类型A出现在值hd的类型A中的逆变位置
因为方法参数计为逆变位置,但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]

动物>:满足动物约束,因为:

Supertype and subtype relationships are reflexive,which means a type
is both a supertype and a subtype of itself. [07002]

cons的论点是Tiger,它符合类型Animal,因此方法调用是类型正确的.

请注意,如果强制将B实例化为Tiger,例如animal_list.cons [Tiger](tiger),则此调用将不是类型正确的,并且您将收到编译器错误.

见类似的例子here.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读