違いが生じる理由は ScalaDoc に記載されています。
ラップされた文字列:
このクラス と の違いは、やStringOps
などの変換メソッドを呼び出すと、 ではなく型のオブジェクトが生成されることです。filter
map
WrappedString
String
StringOps:
このクラス と の違いは、やWrappedString
などの変換メソッドを呼び出すとfilter
オブジェクトmap
が生成されるのString
に対し、WrappedString
は のままであるということWrappedString
です。
collection.GenSeqLike
どちらもequals メソッドを定義する派生元です。
override def equals(that: Any): Boolean = that match {
case that: GenSeq[_] => (that canEqual this) && (this sameElements that)
case _ => false
}
両方とも、常に true を返すcanEqual
(から派生したcollection.IterableLike
) を実装します。しかし、ではありません: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
したがって、最初のケースが返され、もう 1 つのケースが返される理由は明らかfalse
です。
しかし、なぜ両方が存在するのでしょうか。なぜこのように設計されているのかはよくわかりませんが、Scala では String がコレクションではないためだと思います。"abc" flatMap (_+"z")
に示すように、常に可能であるとは限りませんが、別の文字列を取得したいような文字列に対して何らかの操作を行う場合"abc" map (_+1)
。これが何をするかStringOps
です。しかし、何らかのメソッドがある場合def x[A](s: Seq[A]) = s.getClass
、文字列でどのように呼び出すのでしょうか? この場合、次のものが必要ですWrappedString
。
scala> x("a")
res9: Class[_ <: Seq[Char]] = class scala.collection.immutable.WrappedString
だから、StringOps
より軽量WrappedString
です。java.lang.String
これにより、オーバーヘッドをあまりかけずに、plain old でいくつかのメソッドを呼び出すことができます。2.10 ではStringOps
拡張しAnyVal
ます。これは、それが値クラスであり、その存在が scalac によって最適化できることを意味します (文字列をラップすることにより、実行時のオーバーヘッドがなくなります)。対照的WrappedString
に、 String を実際のコレクションとして、つまり として扱うことができますIndexedSeq[Char]
。