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

Scala中方差与可变性/不变性之间的关系

发布时间:2020-12-16 18:54:12 所属栏目:安全 来源:网络整理
导读:我正在玩 Scala中的集合,发现可变集合被定义为不变量,不可变集合被定义为协变. Scala中的方差和可变性/不变性之间的关系是什么? class Array[T]class List[+T] 解决方法 我在SIA找到了一个简单的解释.以下是直接从那里. 可变对象需要是不变的 当一个类型参
我正在玩 Scala中的集合,发现可变集合被定义为不变量,不可变集合被定义为协变. Scala中的方差和可变性/不变性之间的关系是什么?

class Array[T]

class List[+T]

解决方法

我在SIA找到了一个简单的解释.以下是直接从那里.

可变对象需要是不变的
当一个类型参数既不是协变也不是逆变时,它是不变的.所有Scala可变集合类都是不变的.一个例子可以解释为什么可变对象需要是不变的.因为ListBuffer是可变的,所以它被声明为不变,如下所示:

final class ListBuffer[A] ...{ ... }

因为它被声明为不变量,所以不能将ListBuffer从一种类型分配给另一种类型.以下代码将引发编译错误:

scala> val mxs: ListBuffer[String] = ListBuffer("pants")
 mxs: scala.collection.mutable.ListBuffer[String] =
          ListBuffer(pants)
scala> val everything: ListBuffer[Any] = mxs
<console>:6: error: type mismatch;
found   : scala.collection.mutable.ListBuffer[String]
required: scala.collection.mutable.ListBuffer[Any]
     val everything: ListBuffer[Any] = mxs

即使String是scala.Any的子类型,Scala仍然不允许您为所有内容分配mx.为了理解原因,假设ListBuffer是协变的,并且以下代码片段在没有任何编译问题的情况下工作:

scala> val mxs: ListBuffer[String] = ListBuffer("pants")
  mxs: scala.collection.mutable.ListBuffer[String] =
         ListBuffer(pants)
  scala> val everything: ListBuffer[Any] = mxs
  scala> everything += 1
  res4: everything.type = ListBuffer(1,pants)

你能发现问题吗?因为所有内容都是Any类型,所以可以将整数值存储到字符串集合中.这是一场等待发生的灾难.这正是Java数组发生的事情.为了避免这些问题,使可变对象不变是一个好主意.接下来的问题是在集合的不可变对象的情况下会发生什么.事实证明,对于不可变对象,协方差根本不是问题.如果将ListBuffer替换为不可变List,则可以使用List [String]的实例并将其分配给List [Any]而不会出现问题.

scala> val xs: List[String] = List("pants")
xs: List[String] = List(pants)
scala> val everything: List[Any] = xs
everything: List[Any] = List(pants)

这个赋值是安全的唯一原因是因为List是不可变的.您可以向xs List添加1,它将返回Any类型的新List.

scala> 1 :: xs
res5: List[Any] = List(1,pants)

同样,这种添加是安全的,因为cons(::)方法总是返回一个新List,其类型由List中元素的类型决定.唯一可以存储整数值和引用值的类型是scala.Any.在处理可变/不可变对象时,这是记住类型方差的重要属性.

理解逆变的最好方法是看到它不存在时出现的问题.尝试在以下Java代码示例中发现问题:

Object[] arr = new int[1];
arr[0] = "Hello,there!";

您最终将字符串分配给整数数组. Java在运行时通过抛出ArrayStoreException来捕获此错误. Scala通过强制参数类型为逆变或不变来在编译时停止这些类型的错误.

希望这可以帮助.

(编辑:李大同)

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

    推荐文章
      热点阅读