Scala 标准库

Scala 标准库由包 scala 组成,其中包含许多类和模块。以下描述了其中一些类。

Class hierarchy of Scala

基本类型别名

scala 包提供了以下基本类型别名,它们向用户代码公开了一些无法以其他方式编写的 类型 的形式

type AnyKind = ´x´           // where ´x´ is the internal AnyKind type
type Nothing = ´x´           // where ´x´ is the internal Nothing type
type | = [A, B] =>> A ´|´ B // where | is the internal union type operator
type & = [A, B] =>> A ´&´ B // where & is the internal intersection type operator

根类

此层次结构的根是由类 scala.Any 形成的。Scala 执行环境中的每个类都直接或间接地继承自此类。根据定义,Any 也是最顶层的 适当类型。类 Any 具有两个直接子类:AnyRefAnyVal

子类 AnyRef 表示在底层主机系统中以对象形式表示的所有值。用其他语言编写的类继承自 scala.AnyRef

AnyVal 的预定义子类描述了在底层主机系统中未实现为对象的那些值。

未显式继承自 AnyVal 的用户定义的 Scala 类直接或间接地继承自 AnyRef。它们不能同时继承自 AnyRefAnyVal

AnyRefAnyVal 仅需要提供在类 Any 中声明的成员,但实现可能会向这些类添加特定于主机的成员(例如,实现可能会将类 AnyRef 与其自己的对象根类标识)。

以下定义描述了这些根类的签名。

package scala
/** The universal root class */
abstract class Any {

  /** Defined equality; abstract here */
  def equals(that: Any): Boolean

  /** Semantic equality between values */
  final def == (that: Any): Boolean  =
    if (null eq this) null eq that else this equals that

  /** Semantic inequality between values */
  final def != (that: Any): Boolean  =  !(this == that)

  /** Hash code; abstract here */
  def hashCode: Int = ...

  /** Textual representation; abstract here */
  def toString: String = ...

  /** Type test; needs to be inlined to work as given */
  def isInstanceOf[a]: Boolean

  /** Type cast; needs to be inlined to work as given */ */
  def asInstanceOf[A]: A
}

/** The root class of all value types */
final class AnyVal extends Any

/** The root class of all reference types */
class AnyRef extends Any {
  def equals(that: Any): Boolean      = this eq that
  final def eq(that: AnyRef): Boolean = ... // reference equality
  final def ne(that: AnyRef): Boolean = !(this eq that)

  def hashCode: Int = ...     // hashCode computed from allocation address
  def toString: String  = ... // toString computed from hashCode and class name

  def synchronized[T](body: => T): T // execute `body` in while locking `this`.
}

类型测试 ´x´.isInstanceOf[´T´] 等同于一个类型化的模式匹配

´x´ match {
  case _: ´T'´ => true
  case _ => false
}

其中类型 ´T'´ 与 ´T´ 相同,除非 ´T´ 的形式为 ´D´ 或 ´D[\mathit{tps}]´,其中 ´D´ 是某个外部类 ´C´ 的类型成员。在这种情况下,´T'´ 为 ´C´#´D´(或 ´C´#´D[tps]´),而 ´T´ 本身将扩展为 ´C´.this.´D[tps]´。换句话说,isInstanceOf 测试不会检查类型是否具有相同的封闭实例。

如果 ´T´ 是 数值类型,则测试 ´x´.asInstanceOf[´T´] 会被特殊处理。在这种情况下,强制转换将被转换为对 转换方法 x.to´T´ 的应用。对于非数值类型 ´x´,操作将引发 ClassCastException

值类

值类是其实例在底层主机系统中不表示为对象的类。所有值类都继承自类 AnyVal。Scala 实现需要提供值类 UnitBooleanDoubleFloatLongIntCharShortByte(但也可以自由提供其他值类)。这些类的签名在下面定义。

数值类型

DoubleFloatLongIntCharShortByte 统称为数值类型。类 ByteShortChar 称为子范围类型。子范围类型以及 IntLong 称为整数类型,而 FloatDouble 称为浮点类型

数值类型按以下偏序排列

Byte - Short
             \
               Int - Long - Float - Double
             /
        Char

ByteShort 是此顺序中排名最低的类型,而 Double 是排名最高的类型。排名意味着 一致性关系;例如,Int 不是 Long 的子类型。但是,对象 Predef 定义了从每个数值类型到所有更高排名数值类型的 视图。因此,当 上下文 需要时,低排名类型会隐式转换为高排名类型。

给定两个数值类型 ´S´ 和 ´T´,´S´ 和 ´T´ 的操作类型定义如下:如果 ´S´ 和 ´T´ 都是子范围类型,则 ´S´ 和 ´T´ 的操作类型为 Int。否则,´S´ 和 ´T´ 的操作类型是两个类型中排名较高的那个。给定两个数值 ´v´ 和 ´w´,´v´ 和 ´w´ 的操作类型是其运行时类型的操作类型。

任何数值类型 ´T´ 都支持以下方法。

整数数值类型除了上述操作外,还支持以下操作

数值类型还实现了 Any 类中的 equalshashCodetoString 操作。

equals 方法测试参数是否为数值类型。如果为真,它将执行适合该类型的 == 操作。也就是说,数值类型的 equals 方法可以被认为是如下定义的

def equals(other: Any): Boolean = other match {
  case that: Byte   => this == that
  case that: Short  => this == that
  case that: Char   => this == that
  case that: Int    => this == that
  case that: Long   => this == that
  case that: Float  => this == that
  case that: Double => this == that
  case _ => false
}

hashCode 方法返回一个整数哈希码,它将相等的数值映射到相等的结果。对于 Int 类型和所有子范围类型,它保证是恒等式。

toString 方法将接收者显示为整数或浮点数。

示例

这是数值类型 Int 的签名

package scala
abstract sealed class Int extends AnyVal {
  def == (that: Double): Boolean  // double equality
  def == (that: Float): Boolean   // float equality
  def == (that: Long): Boolean    // long equality
  def == (that: Int): Boolean     // int equality
  def == (that: Short): Boolean   // int equality
  def == (that: Byte): Boolean    // int equality
  def == (that: Char): Boolean    // int equality
  /* analogous for !=, <, >, <=, >= */

  def + (that: Double): Double    // double addition
  def + (that: Float): Double     // float addition
  def + (that: Long): Long        // long addition
  def + (that: Int): Int          // int addition
  def + (that: Short): Int        // int addition
  def + (that: Byte): Int         // int addition
  def + (that: Char): Int         // int addition
  /* analogous for -, *, /, % */

  def & (that: Long): Long        // long bitwise and
  def & (that: Int): Int          // int bitwise and
  def & (that: Short): Int        // int bitwise and
  def & (that: Byte): Int         // int bitwise and
  def & (that: Char): Int         // int bitwise and
  /* analogous for |, ^ */

  def << (cnt: Int): Int          // int left shift
  def << (cnt: Long): Int         // long left shift
  /* analogous for >>, >>> */

  def unary_+ : Int               // int identity
  def unary_- : Int               // int negation
  def unary_~ : Int               // int bitwise negation

  def toByte: Byte                // convert to Byte
  def toShort: Short              // convert to Short
  def toChar: Char                // convert to Char
  def toInt: Int                  // convert to Int
  def toLong: Long                // convert to Long
  def toFloat: Float              // convert to Float
  def toDouble: Double            // convert to Double
}

Boolean

Boolean 只有两个值:truefalse。它实现了以下类定义中给出的操作。

package scala
abstract sealed class Boolean extends AnyVal {
  def && (p: => Boolean): Boolean = // boolean and
    if (this) p else false
  def || (p: => Boolean): Boolean = // boolean or
    if (this) true else p
  def &  (x: Boolean): Boolean =    // boolean strict and
    if (this) x else false
  def |  (x: Boolean): Boolean =    // boolean strict or
    if (this) true else x
  def == (x: Boolean): Boolean =    // boolean equality
    if (this) x else x.unary_!
  def != (x: Boolean): Boolean =    // boolean inequality
    if (this) x.unary_! else x
  def unary_!: Boolean =            // boolean negation
    if (this) false else true
}

该类还实现了来自类 Any 的操作 equalshashCodetoString

equals 方法如果参数与接收者是相同的布尔值,则返回 true,否则返回 falsehashCode 方法在调用 true 时返回一个固定的、特定于实现的哈希码,在调用 false 时返回一个不同的、固定的、特定于实现的哈希码。toString 方法返回接收者转换为字符串,即 "true""false"

Unit

Unit 只有一个值:()。它只实现了来自类 Any 的三个方法 equalshashCodetoString

equals 方法如果参数是单元值 (),则返回 true,否则返回 falsehashCode 方法返回一个固定的、特定于实现的哈希码。toString 方法返回 "()"

标准引用类

本节介绍一些标准的 Scala 引用类,它们在 Scala 编译器中以特殊方式处理 - Scala 为它们提供语法糖,或者 Scala 编译器为它们的操作生成特殊代码。标准 Scala 库中的其他类在 Scala 库文档中由 HTML 页面记录。

String

Scala 的 String 类通常派生自底层主机系统的标准 String 类(并且可能与其相同)。对于 Scala 客户端,该类被认为在每种情况下都支持一个方法

def + (that: Any): String

它将左操作数与其右操作数的文本表示形式连接起来。

Function

对于每个自然数 ´n \geq 0´,scala 包定义了以下函数类

package scala
trait Function´_n´[-´T_1´, ..., -´T_n´, +´R´]:
  def apply(´x_1´: ´T_1´, ..., ´x_n´: ´T_n´): ´R´

这些类参与 具体函数类型 的脱糖。

对于 ´n \leq 22´ 的值,Function´_n´ 类定义了额外的函数

package scala
trait Function´_n´[-´T_1´, ..., -´T_n´, +´R´]:
  ...
  override def toString = "<function´_n´>"
  def curried: ´T_1´ => ... => ´T_n´ => R = ...
  def tupled: ((´T_1´, ..., ´T_n´)) => R = ...

隐式导入的 Predef 对象将名称 Function 定义为 Function1 的别名。

Function1 的子类 PartialFunction 表示(间接)指定其域的函数。使用 isDefined 方法查询部分函数是否为给定输入定义(即,输入是否为函数域的一部分)。

class PartialFunction[-A, +B] extends Function1[A, B] {
  def isDefinedAt(x: A): Boolean

  ... // various derived methods
}

PartialFunction 参与 模式匹配匿名函数 的脱糖。

特质 Product

所有案例类自动扩展 Product 特质(并生成合成方法以符合它)(但不是 Product´n´),并为其每个参数定义 _´n´ 方法。

特质 Enum

所有枚举定义自动扩展 reflect.Enum 特质(并生成合成方法以符合它)。

元组类

元组是以下类定义的HLists 的一种形式

/** Superclass of all tuples. */
sealed trait Tuple extends Product:
  /** Return a new tuple by prepending the element to `this` tuple. */
  inline def *: [H, This >: this.type <: Tuple] (x: H): H *: This = ...
  ...

object Tuple:
  /** Type of the element at position N in the tuple X. */
  type Elem[X <: Tuple, N <: Int] = ...
  ...

/** A tuple of 0 elements. */
type EmptyTuple = EmptyTuple.type

/** A tuple of 0 elements. */
case object EmptyTuple extends Tuple:
  override def toString(): String = "()"

/** Tuple of arbitrary non-zero arity */
sealed trait NonEmptyTuple extends Tuple:
  /** Get the i-th element of this tuple. */
  inline def apply[This >: this.type <: NonEmptyTuple](n: Int): Elem[This, n.type] = ...
  ...

sealed abstract class *:[+H, +T <: Tuple] extends NonEmptyTuple

object `*:` :
  def unapply[H, T <: Tuple](x: H *: T): (H, T) = (x.head, x.tail)

对于 ´1 \leq n \leq 22´,*: 的具体实现是 Tuple´_n´ 类的实例,它们也实现了相应的 Product´_n´ 特质。它们至少在标准 Scala 库中定义如下(它们也可能添加其他方法并实现其他特质)。

trait Product´_n´[+´T_1´, ..., +´T_n´] extends Product:
  override def productArity: Int = ´n´
  def _1: ´T_1´
  ...
  def _n: ´T_n´

final case class Tuple´_n´[+´T_1´, ..., +´T_n´](_1: ´T_1´, ..., _n: ´T_n´)
    extends *:[´T_1´, ´T_2´ *: ... _: ´T_n´ *: EmptyTuple]
    with Product´_n´[´T_1´, ..., ´T_n´]

对于 ´n > 22´,*: 的具体实现是特定于实现的私有类的实例。

Array

数组上的所有操作都脱糖为底层平台的相应操作。因此,以下类定义仅供参考

final class Array[T](_length: Int)
extends java.io.Serializable with java.lang.Cloneable {
  def length: Int = ...
  def apply(i: Int): T = ...
  def update(i: Int, x: T): Unit = ...
  override def clone(): Array[T] = ...
}

如果 ´T´ 不是类型参数或抽象类型,则类型 Array[T] 在底层主机系统中表示为数组类型 |T|[],其中 |T|T 的擦除。如果 ´T´ 是类型参数或抽象类型,则可能使用不同的表示(在 Java 平台上为 Object)。

操作

length 返回数组的长度,apply 表示下标,update 表示元素更新。

由于 applyupdate 操作的语法糖,我们对数组 xs 上的操作有以下 Scala 和 Java 代码之间的对应关系

Scala Java
xs.length xs.length
xs(i) xs[i]
xs(i) = e xs[i] = e

Predef 中存在两种对数组经常使用的隐式转换:转换为 scala.collection.mutable.ArrayOps 和转换为 scala.collection.mutable.ArraySeqscala.collection.Seq 的子类型)。

这两种类型都使 Scala 集合 API 中的许多标准操作可用。转换为 ArrayOps 是临时的,因为在 ArrayOps 上定义的所有操作都返回类型为 Array 的值,而转换为 ArraySeq 是永久性的,因为所有操作都返回类型为 ArraySeq 的值。转换为 ArrayOps 优先于转换为 ArraySeq

由于 Scala 中参数化类型和宿主语言中数组的 ad-hoc 实现之间的紧张关系,在处理数组时需要考虑一些微妙的点。这些将在下面解释。

方差

与 Java 中的数组不同,Scala 中的数组 *不是* 协变的;也就是说,´S <: T´ 在 Scala 中并不意味着 Array[´S´] ´<:´ Array[´T´]。但是,如果宿主环境允许,则可以将 ´S´ 数组强制转换为 ´T´ 数组。

例如,Array[String] 不符合 Array[Object],即使 String 符合 Object。但是,可以将类型为 Array[String] 的表达式强制转换为 Array[Object],并且此强制转换将在不引发 ClassCastException 的情况下成功。示例

val xs = new Array[String](2)
// val ys: Array[Object] = xs   // **** error: incompatible types
val ys: Array[Object] = xs.asInstanceOf[Array[Object]] // OK

使用多态元素类型 ´T´ 实例化数组需要在运行时有关类型 ´T´ 的信息。此信息是通过向类型 ´T´ 添加 scala.reflect.ClassTag上下文界限 来合成的。一个例子是以下 mkArray 方法的实现,该方法创建任意类型 ´T´ 的数组,给定一个定义其元素的 ´T´ 序列

import reflect.ClassTag
def mkArray[T : ClassTag](elems: Seq[T]): Array[T] = {
  val result = new Array[T](elems.length)
  var i = 0
  for (elem <- elems) {
    result(i) = elem
    i += 1
  }
  result
}

如果类型 ´T´ 是宿主平台提供专门数组表示的类型,则使用此表示。

示例

在 Java 虚拟机上,调用 mkArray(List(1,2,3)) 将返回一个 int 的原始数组,在 Java 中写为 int[]

伴随对象

Array 的伴随对象提供了用于实例化一维和多维数组的各种工厂方法,一个提取器方法 unapplySeq,它允许对数组进行模式匹配,以及其他实用程序方法

package scala
object Array {
  /** copies array elements from `src` to `dest`. */
  def copy(src: AnyRef, srcPos: Int,
           dest: AnyRef, destPos: Int, length: Int): Unit = ...

  /** Returns an array of length 0 */
  def empty[T: ClassTag]: Array[T] =

  /** Create an array with given elements. */
  def apply[T: ClassTag](xs: T*): Array[T] = ...

  /** Creates array with given dimensions */
  def ofDim[T: ClassTag](n1: Int): Array[T] = ...
  /** Creates a 2-dimensional array */
  def ofDim[T: ClassTag](n1: Int, n2: Int): Array[Array[T]] = ...
  ...

  /** Concatenate all argument arrays into a single array. */
  def concat[T: ClassTag](xss: Array[T]*): Array[T] = ...

  /** Returns an array that contains the results of some element computation a number
    * of times. */
  def fill[T: ClassTag](n: Int)(elem: => T): Array[T] = ...
  /** Returns a two-dimensional array that contains the results of some element
    * computation a number of times. */
  def fill[T: ClassTag](n1: Int, n2: Int)(elem: => T): Array[Array[T]] = ...
  ...

  /** Returns an array containing values of a given function over a range of integer
    * values starting from 0. */
  def tabulate[T: ClassTag](n: Int)(f: Int => T): Array[T] = ...
  /** Returns a two-dimensional array containing values of a given function
    * over ranges of integer values starting from `0`. */
  def tabulate[T: ClassTag](n1: Int, n2: Int)(f: (Int, Int) => T): Array[Array[T]] = ...
  ...

  /** Returns an array containing a sequence of increasing integers in a range. */
  def range(start: Int, end: Int): Array[Int] = ...
  /** Returns an array containing equally spaced values in some integer interval. */
  def range(start: Int, end: Int, step: Int): Array[Int] = ...

  /** Returns an array containing repeated applications of a function to a start value. */
  def iterate[T: ClassTag](start: T, len: Int)(f: T => T): Array[T] = ...

  /** Enables pattern matching over arrays */
  def unapplySeq[A](x: Array[A]): Option[IndexedSeq[A]] = Some(x)
}

类节点

package scala.xml

trait Node {

  /** the label of this node */
  def label: String

  /** attribute axis */
  def attribute: Map[String, String]

  /** child axis (all children of this node) */
  def child: Seq[Node]

  /** descendant axis (all descendants of this node) */
  def descendant: Seq[Node] = child.toList.flatMap {
    x => x::x.descendant.asInstanceOf[List[Node]]
  }

  /** descendant axis (all descendants of this node) */
  def descendant_or_self: Seq[Node] = this::child.toList.flatMap {
    x => x::x.descendant.asInstanceOf[List[Node]]
  }

  override def equals(x: Any): Boolean = x match {
    case that:Node =>
      that.label == this.label &&
        that.attribute.sameElements(this.attribute) &&
          that.child.sameElements(this.child)
    case _ => false
  }

 /** XPath style projection function. Returns all children of this node
  *  that are labeled with 'that'. The document order is preserved.
  */
    def \(that: Symbol): NodeSeq = {
      new NodeSeq({
        that.name match {
          case "_" => child.toList
          case _ =>
            var res:List[Node] = Nil
            for (x <- child.elements if x.label == that.name) {
              res = x::res
            }
            res.reverse
        }
      })
    }

 /** XPath style projection function. Returns all nodes labeled with the
  *  name 'that' from the 'descendant_or_self' axis. Document order is preserved.
  */
  def \\(that: Symbol): NodeSeq = {
    new NodeSeq(
      that.name match {
        case "_" => this.descendant_or_self
        case _ => this.descendant_or_self.asInstanceOf[List[Node]].
        filter(x => x.label == that.name)
      })
  }

  /** hashcode for this XML node */
  override def hashCode =
    Utility.hashCode(label, attribute.toList.hashCode, child)

  /** string representation of this node */
  override def toString = Utility.toXML(this)

}

Predef 对象

Predef 对象为 Scala 程序定义了标准方法和类型别名。它被隐式导入,如 关于名称绑定的章节 中所述,因此所有定义的成员都可以在没有限定符的情况下使用。它在 JVM 环境中的定义符合以下签名

package scala
object Predef {

  // classOf ---------------------------------------------------------

  /** Returns the runtime representation of a class type. */
  def classOf[T]: Class[T] = null
   // this is a dummy, classOf is handled by compiler.

  // valueOf -----------------------------------------------------------

  /** Retrieve the single value of a type with a unique inhabitant. */
  @inline def valueOf[T](implicit vt: ValueOf[T]): T {} = vt.value
   // instances of the ValueOf type class are provided by the compiler.

  // Standard type aliases ---------------------------------------------

  type String    = java.lang.String
  type Class[T]  = java.lang.Class[T]

  // Miscellaneous -----------------------------------------------------

  type Function[-A, +B] = Function1[A, B]

  type Map[A, +B] = collection.immutable.Map[A, B]
  type Set[A] = collection.immutable.Set[A]

  val Map = collection.immutable.Map
  val Set = collection.immutable.Set

  // Manifest types, companions, and incantations for summoning ---------

  type ClassManifest[T] = scala.reflect.ClassManifest[T]
  type Manifest[T]      = scala.reflect.Manifest[T]
  type OptManifest[T]   = scala.reflect.OptManifest[T]
  val ClassManifest     = scala.reflect.ClassManifest
  val Manifest          = scala.reflect.Manifest
  val NoManifest        = scala.reflect.NoManifest

  def manifest[T](implicit m: Manifest[T])           = m
  def classManifest[T](implicit m: ClassManifest[T]) = m
  def optManifest[T](implicit m: OptManifest[T])     = m

  // Minor variations on identity functions -----------------------------
  def identity[A](x: A): A         = x
  def implicitly[T](implicit e: T) = e    // for summoning implicit values from the nether world
  @inline def locally[T](x: T): T  = x    // to communicate intent and avoid unmoored statements

  // Asserts, Preconditions, Postconditions -----------------------------

  def assert(assertion: Boolean) {
    if (!assertion)
      throw new java.lang.AssertionError("assertion failed")
  }

  def assert(assertion: Boolean, message: => Any) {
    if (!assertion)
      throw new java.lang.AssertionError("assertion failed: " + message)
  }

  def assume(assumption: Boolean) {
    if (!assumption)
      throw new IllegalArgumentException("assumption failed")
  }

  def assume(assumption: Boolean, message: => Any) {
    if (!assumption)
      throw new IllegalArgumentException("assumption failed: " + message.toString)
  }

  def require(requirement: Boolean) {
    if (!requirement)
      throw new IllegalArgumentException("requirement failed")
  }

  def require(requirement: Boolean, message: => Any) {
    if (!requirement)
      throw new IllegalArgumentException("requirement failed: "+ message)
  }
  // Printing and reading -----------------------------------------------

  def print(x: Any) = Console.print(x)
  def println() = Console.println()
  def println(x: Any) = Console.println(x)
  def printf(text: String, xs: Any*) = Console.printf(text.format(xs: _*))

  // Implicit conversions ------------------------------------------------

  ...
}

预定义的隐式定义

Predef 对象还包含许多隐式定义,这些定义默认情况下可用(因为 Predef 被隐式导入)。隐式定义分为两种优先级。高优先级隐式定义在 Predef 类本身中定义,而低优先级隐式定义在 Predef 继承的类中定义。静态 重载解析 的规则规定,在所有其他条件相同的情况下,隐式解析优先选择高优先级隐式而不是低优先级隐式。

可用的低优先级隐式定义包括以下类别。

  1. 对于每种原始类型,一个包装器,它将该类型的值转换为 `runtime.Rich*` 类的实例。例如,类型为 `Int` 的值可以隐式转换为 `runtime.RichInt` 类的实例。

  2. 对于每种元素为原始类型的数组类型,一个包装器,它将该类型的数组转换为 `ArraySeq` 类的实例。例如,类型为 `Array[Float]` 的值可以隐式转换为 `ArraySeq[Float]` 类的实例。还有一些泛型数组包装器,它们将类型为 `Array[T]` 的元素(对于任意 `T`)转换为 `ArraySeq`。

  3. 从 `String` 到 `WrappedString` 的隐式转换。

可用的高优先级隐式定义包括以下类别。