StringOps和WrappedString实例之间的平等

时间:2012-06-17 01:52:41

标签: scala

我只是在学习Scala,所以如果已经讨论过这个问题我会道歉,但以下对我来说似乎有些奇怪:

scala> import scala.collection.immutable._
import scala.collection.immutable._

scala> val st1 = new WrappedString("Hello")
st1: scala.collection.immutable.WrappedString = Hello

scala> val st2 = new StringOps("Hello")
st2: scala.collection.immutable.StringOps = Hello

scala> st2 == st1
res0: Boolean = true

scala> st1 == st2
res1: Boolean = false

任何人都能解释一下吗?我使用的是Scala版本2.10.0-M4。我没试过这个 其他任何版本。

1 个答案:

答案 0 :(得分:6)

ScalaDoc中记录了出现差异的原因。

WrappedString:

  

此类与StringOps之间的区别在于调用   变换器方法,如filtermap将产生一个对象   键入WrappedString而不是String

StringOps:

  

此类与WrappedString之间的区别在于调用   filtermap之类的变换器方法将产生String   对象,而WrappedString将保持为WrappedString

两者都派生自定义等于方法的collection.GenSeqLike

override def equals(that: Any): Boolean = that match {
  case that: GenSeq[_] => (that canEqual this) && (this sameElements that)
  case _ => false
}

两者都实现了canEqual(源自collection.IterableLikereturns always true。但StringOps不是collection.GenIterable

scala> st1 sameElements st2
<console>:13: error: type mismatch;
 found   : scala.collection.immutable.StringOps
 required: scala.collection.GenIterable[?]
              st1 sameElements st2
                               ^

WrappedString确实:

scala> st2 sameElements st1
res13: Boolean = true

所以很明显为什么第一个案例会返回true而另一个案例会false

但为什么两者都存在?我不完全确定为什么它是这样设计的,但我认为这是因为String不是Scala中的集合。当我们对像"abc" flatMap (_+"z")这样的字符串执行某些操作时,我们想要获得另一个字符串,即使"abc" map (_+1)所示并不总是这样。这就是StringOps的作用。但是当我们有一些方法def x[A](s: Seq[A]) = s.getClass时,我们如何用String调用它?在这种情况下,我们需要WrappedString

scala> x("a")
res9: Class[_ <: Seq[Char]] = class scala.collection.immutable.WrappedString

因此,StringOpsWrappedString更轻量级。它允许我们在普通的java.lang.String上调用一些方法而不需要太多的开销。在2.10 StringOps扩展AnyVal。这意味着它是一个值类,它的存在可以通过scalac进行优化(通过包装String不再有运行时开销)。相比之下,WrappedString允许我们将String作为真实集合处理 - 作为IndexedSeq[Char]