Scala学习笔记(4):关于String

Scala并没有定义自己的String类型,而是直接借用了Java中的String,所以如果你定义一个String类型的值:

val str = "hello"
返回的值的类型直接就是java.lang.String。然而,我们知道在Scala中可以像使用List一样来操作String值,例如:
str.reverse  //String = olleh
str.map(_.toUpper)  //String = HELLO
str drop 3  //String = lo
str slice (1, 4)  //String = ell
val s: Seq[Char] = str

但是,map, drop,slice等操作并没有在java.lang.String中定义,为什么可以直接在这里使用?

熟悉C#的同学应该都知道C#提供了extends method来扩展已有的类库,来给外部类型定义新的方法。Scala不支持extends method,但是提供了implicit conversion(隐式转换),它可以实现同样的效果而且更加灵活。感兴趣的同学可以看看这个视频。

究竟什么是implicit conversions?其实就是进行从一个类型到另一个类型的隐式转换。例如下面这个例子把一个Float值赋给一个Int变量,默认是出错的:

scala> val i: Int = 3.5
<console>:4: error: type mismatch;
found : Double(3.5)
required: Int
val i: Int = 3.5
但是如果定义一个implicit转换函数,就可以做到隐式转换。
implicit def doubleToInt(x: Double) = x.toInt

scala> val i: Int = 3.5
i: Int = 3

上面说的是implicit函数,在Scala 2.10中又新增了implicit class这个功能,可以更加方便地进行类型转换。具体可以看这个文档。

回到String类型,实际上Scala在java.lang.String上定义了两个不同优先级的implicit conversion,按需要编译器会自动选择使用:

  1. 优先级低的转换,把String类型被转成WrappedString类型,该类型是immutable.IndexedSeq的一个子类。在下面这个例子中就用到了这个隐式转换
    val s: Seq[Char] = str
  2. 优先级高的转换,把String类型转换成StringOps,其中包括了所有immutable sequence的方法。在碰到reverse, map, drop和slice方法时编译器会自动插入这个转换。

这种基于隐式转换的类型扩展,值得在实际Scala编程中实践。

你可能感兴趣的:(scala)