Scala-可变集合中的协变类型 [英] Scala - covariant type in mutable collections

查看:128
本文介绍了Scala-可变集合中的协变类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Scala世界中的新手,现在我正在阅读名为《 Scala in Action》(由Nilanjan Raychaudhuri撰写)的书,即第97页上的"Mutable object必须是不变的"部分,我不理解以下部分直接取自上述书籍.

I am new in Scala world and now I am reading the book called "Scala in Action" (by Nilanjan Raychaudhuri), namely the part called "Mutable object need to be invariant" on page 97 and I don't understand the following part which is taken directly from the mentioned book.

假设ListBuffer是协变的,并且以下代码段可以正常工作,而不会出现任何编译问题:

Assume ListBuffer is covariant and the following code snippet works without any compilation problem:

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)

您能发现问题吗?由于所有内容均为任意"类型,因此您可以存储 将整数值转换为字符串集合.这是一场灾难,等待发生.为避免此类问题,始终 使可变对象不变的好主意.

Can you spot the problem? Because everything is of the type Any, you can store an integer value into a collection of strings. This is a disaster waiting to happen. To avoid these kinds of problems, it’s always a good idea to make mutable objects invariant.

我会有以下问题.

1)实际上是什么类型的everything? String还是Any?声明为"val everything: ListBuffer[Any]",因此我希望使用Any,并且由于所有内容都应为Any类型,所以我看不到将IntegerString放在一个ListBuffer[Any]中的任何问题.我如何将整数值存储到字符串集合中,它们是如何编写的???为什么会灾难???为什么要使用List(不可变)而不是ListBuffer(可变)?我没看见有分别.我发现很多答案,可变集合应该具有类型不变,而可变集合应该具有协变量类型,但是为什么呢?

1) What type of everything is in reality? String or Any? The declaration is "val everything: ListBuffer[Any]" and hence I would expect Any and because everything should be type of Any then I don't see any problems to have Integer and String in one ListBuffer[Any]. How can I store integer value into collection of strings how they write??? Why disaster??? Why should I use List (which is immutable) instead of ListBuffer (which is mutable)? I see no difference. I found a lot of answers that mutably collections should have type invariant and that immutable collections should have covariant type but why?

2)最后一部分"res4: everything.type = ListBuffer(1, pants)"是什么意思? "everything.type"是什么意思?我想everything没有名为type的任何方法/函数或变量.为什么没有ListBuffer [Any]或ListBuffer [String]?

2) What does the last part "res4: everything.type = ListBuffer(1, pants)" mean? What does "everything.type" mean? I guess that everything does not have any method/function or variable called type.. Why is there no ListBuffer[Any] or ListBuffer[String]?

非常感谢

安德鲁

推荐答案

1 这看起来不是一个单一的问题,因此我必须对其进行进一步细分:

1 This doesn't look like a single question, so I have to subdivide it further:

  1. 实际上" everythingListBuffer[_],参数类型已删除.根据JVM,它包含对某些对象的32位或64位引用.类型ListBuffer[String]ListBuffer[Any]是编译器在编译时所知道的.如果它知道"两个矛盾的事情,那么显然很糟糕.
  2. 在使用Integer和String时,我看不到任何问题 一个ListBuffer [Any]".在ListBuffer[Any]中包含IntString是没有问题的,因为ListBuffer是不变的.但是,在您的假设示例中,ListBuffer是协变的,因此您正在将Int存储在ListBuffer[String]中.如果以后有人从ListBuffer[String]获取Int,并试图将其解释为String,那么显然很糟糕.

  1. "In reality" everything is ListBuffer[_], with erased parameter type. Depending on the JVM, it holds either 32 or 64 bit references to some objects. The types ListBuffer[String] and ListBuffer[Any] is what the compiler knows about it at compile time. If it "knows" two contradictory things, then it's obviously very bad.
  2. "I don't see any problems to have Integer and String in one ListBuffer[Any]". There is no problem to have Int and String in ListBuffer[Any], because ListBuffer is invariant. However, in your hypothetical example, ListBuffer is covariant, so you are storing an Int in a ListBuffer[String]. If someone later gets an Int from a ListBuffer[String], and tries to interpret it as String, then it's obviously very bad.

如何将整数值存储到集合中 字符串是怎么写的?" 为什么您要做如上所述显然很糟糕的事情?

"How can I store integer value into collection of strings how they write?" Why would you want to do something that is obviously very bad, as explained above?

为什么会发生灾难?" 这不会是大灾难. Java一直都在使用协变数组.它不会导致大灾变,只是很糟糕而且很烦人.

"Why disaster???" It wouldn't be a major disaster. Java has been living with covariant arrays forever. It's does not lead to cataclysms, it's just bad and annoying.

为什么我应该使用List(不可变)而不是ListBuffer(可变)?" 没有绝对的必要条件告诉您始终使用List并永远不要使用ListBuffer.适当时请同时使用两者.在99.999%的情况下,List当然更合适,因为与设计需要ListBuffer局部可变状态的复杂算法相比,使用List表示数据的频率更高.

"Why should I use List (which is immutable) instead of ListBuffer (which is mutable)?" There is no absolute imperative that tells you to always use List and to never use ListBuffer. Use both when it is appropriate. In 99.999% of cases, List is of course more appropriate, because you use Lists to represent data way more often than you design complicated algorithms that require local mutable state of a ListBuffer.

我发现了很多可变的答案 应该具有类型不变性,并且不可变的集合应该 具有协变类型,但为什么呢?" .这是错误的,您过于简化了.例如,内涵不可变集既不应该协变也不应该不变,而应该是 contravariant .您应该使用协变这个小小的愚蠢的例子被证明对解释这种差别是不合理的有效,也许你也发现了它很有用.

"I found a lot of answers that mutably collections should have type invariant and that immutable collections should have covariant type but why?". This is wrong, you are over-simplifying. For example, intensional immutable sets should be neither covariant, nor invariant, but contravariant. You should use covariance, contravariance, and invariance when it's appropriate. This little silly illustration has proven unreasonably effective for explaining the difference, maybe you too find it useful.

2 这是单例类型,如以下示例所示:

2 This is a singleton type, just like in the following example:

scala> val x = "hello"
x: String = hello

scala> val y: x.type = x
y: x.type = hello

这是关于动机的更长时间的讨论

这篇关于Scala-可变集合中的协变类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆