Scala 例 文字列 String
ScalaのStringについて、調べてみる。暗黙の型変換、implicit defの話題もある。
ScalaのStringは、Javaのjava.lang.Stringそのもの。
scala> val a = "abcd" a: java.lang.String = abcd scala> a.getClass res14: java.lang.Class[_] = class java.lang.String
さすがに、なんでも自前で用意ってわけじゃないんだな。再利用、再利用。
はなしが変わるけど、Scala Standard Library 2.12.8 - scala.Predefには、type Stringが定義してある。この場合は、単純に、java.lang.Stringに対して、短い別名Stringを定義しているだけのようだ。
type String = java.lang.String
ここまでは「typeなんてあるんだ。ふーん」って感じだが、Scalaを学びはじめているときには、Stringには、ちょっとおもしろいところがある。
それは、ただのjava.lang.Stringオブジェクトのはずなのに、java.lang.Stringにはないメソッドがつかえるところ。
scala> "abcd" res19: java.lang.String = abcd scala> "abcd".toList res20: List[Char] = List(a, b, c, d) scala> "%04d".format(100) res21: String = 0100
java.lang.Stringについては、toListメソッドなんてないし、formatメソッドも、staticメソッドであり、また、うえの例のような、シグニチャではない。
Oracle Technology Network for Java Developers | Oracle Technology Network | Oracle
ちょっと、ScalaのStringを調べてみると、
scala> "abcd".getClass.getMethods.filter(_.getName == "toList") なにもない scala> "abcd".getClass.getMethods.filter(_.getName == "format").foreach(println) public static java.lang.String java.lang.String.format(java.lang.String,java.lang.Object[]) public static java.lang.String java.lang.String.format(java.util.Locale,java.lang.String,java.lang.Object[])
上のように、ありもしないメソッドを実行できるように見えるのは、Scalaの暗黙の型変換とよばれる機能によるもの。
あらかじめimplicit defで定義しておくと、必要に応じて、あるクラスのオブジェクトが別のクラスのオブジェクトに変換される。
java.lang.Stringについて、ふたたびScala Standard Library 2.12.8 - scala.Predefを見ると、
implicit def augmentString(x: String): StringOps = new StringOps(x)
が定義してある。
これによって、java.lang.Stringオブジェクトは、Scala Standard Library 2.12.8 - scala.collection.immutable.StringOpsオブジェクトに自動的に変換される。
ソースコードとしては、パッと見て、java.lang.Stringオブジェクトをあつかっているはずなのに、Scala Standard Library 2.12.8 - scala.collection.immutable.StringOpsオブジェクトをあつかっているかのように記述することができる。
繰り返しになるが、java.lang.Stringにないメソッドが、いろいろ使えるようになる。
Scalaは、妙に機能豊富なところがあって、「気持ちわるい」「わかりづらい」という気がしなくもない。あるとき、突然、当たり前に便利に感じるようになるのかな。
下の例では、StringOpsのメソッドにより、Stringについて、正規表現のパターンを生成したり、Listに変換したり。
scala> val p = "([A-Z])".r p: scala.util.matching.Regex = ([A-Z]) scala> "abCdEf".toList res67: List[Char] = List(a, b, C, d, E, f)