Scala 教程

语言

Scala 中的类是用于创建对象的蓝图。它们可以包含方法、值、变量、类型、对象、特征和类,这些统称为成员。类型、对象和特征将在本教程后面进行介绍。

定义类

最简单的类定义仅包含关键字 class 和一个标识符。类名应大写。

class User

val user1 = new User

关键字 new 用于创建类的实例。

class User

val user1 = User()

我们像调用函数一样调用类,例如 User(),以创建类的实例。也可以明确使用 new 关键字,例如 new User(),尽管通常省略该关键字。

User 有一个默认构造函数,该函数不接受任何参数,因为没有定义构造函数。但是,你通常需要一个构造函数和类主体。下面是一个点的示例类定义

class Point(var x: Int, var y: Int) {

  def move(dx: Int, dy: Int): Unit = {
    x = x + dx
    y = y + dy
  }

  override def toString: String =
    s"($x, $y)"
}

val point1 = new Point(2, 3)
println(point1.x)  // prints 2
println(point1)    // prints (2, 3)
class Point(var x: Int, var y: Int):

  def move(dx: Int, dy: Int): Unit =
    x = x + dx
    y = y + dy

  override def toString: String =
    s"($x, $y)"
end Point

val point1 = Point(2, 3)
println(point1.x)  // prints 2
println(point1)    // prints (2, 3)

Point 类有四个成员:变量 xy,以及方法 movetoString。与许多其他语言不同,主构造函数在类签名 (var x: Int, var y: Int) 中。 move 方法接受两个整型参数,并返回单位值 (),该值不携带任何信息。这大致对应于类似 Java 的语言中的 void。另一方面, toString 不接受任何参数,但返回 String 值。由于 toString 覆盖了 AnyRef 中的 toString,因此它被标记为 override 关键字。

构造函数

构造函数可以通过提供默认值来具有可选参数,如下所示

class Point(var x: Int = 0, var y: Int = 0)

val origin = new Point    // x and y are both set to 0
val point1 = new Point(1) // x is set to 1 and y is set to 0
println(point1)           // prints (1, 0)
class Point(var x: Int = 0, var y: Int = 0)

val origin = Point()  // x and y are both set to 0
val point1 = Point(1) // x is set to 1 and y is set to 0
println(point1)       // prints (1, 0)

在此版本的 Point 类中, xy 的默认值 0,因此不需要参数。但是,由于构造函数从左到右读取参数,因此如果你只想传入 y 值,则需要命名参数。

class Point(var x: Int = 0, var y: Int = 0)
val point2 = new Point(y = 2)
println(point2)               // prints (0, 2)
class Point(var x: Int = 0, var y: Int = 0)
val point2 = Point(y = 2)
println(point2)           // prints (0, 2)

这也是提高清晰度的好做法。

私有成员和 Getter/Setter 语法

成员默认情况下为公共。使用 private 访问修饰符将它们隐藏在类外部。

class Point {
  private var _x = 0
  private var _y = 0
  private val bound = 100

  def x: Int = _x
  def x_=(newValue: Int): Unit = {
    if (newValue < bound)
      _x = newValue
    else
      printWarning()
  }

  def y: Int = _y
  def y_=(newValue: Int): Unit = {
    if (newValue < bound)
      _y = newValue
    else
      printWarning()
  }

  private def printWarning(): Unit =
    println("WARNING: Out of bounds")
}

val point1 = new Point
point1.x = 99
point1.y = 101 // prints the warning
class Point:
  private var _x = 0
  private var _y = 0
  private val bound = 100

  def x: Int = _x
  def x_=(newValue: Int): Unit =
    if newValue < bound then
      _x = newValue
    else
      printWarning()

  def y: Int = _y
  def y_=(newValue: Int): Unit =
    if newValue < bound then
      _y = newValue
    else
      printWarning()

  private def printWarning(): Unit =
    println("WARNING: Out of bounds")
end Point

val point1 = Point()
point1.x = 99
point1.y = 101 // prints the warning

在此版本的 Point 类中,数据存储在私有变量 _x_y 中。有方法 def xdef y 用于访问私有数据。 def x_=def y_= 用于验证和设置 _x_y 的值。注意设置器的特殊语法:方法在 getter 的标识符后附加 _=,并且参数在之后。

带有 valvar 的主构造函数参数是公共的。但是,由于 val 是不可变的,因此无法编写以下内容。

class Point(val x: Int, val y: Int)
val point = new Point(1, 2)
point.x = 3  // <-- does not compile
class Point(val x: Int, val y: Int)
val point = Point(1, 2)
point.x = 3  // <-- does not compile

没有 valvar 的参数是私有值,仅在类内可见。

class Point(x: Int, y: Int)
val point = new Point(1, 2)
point.x  // <-- does not compile
class Point(x: Int, y: Int)
val point = Point(1, 2)
point.x  // <-- does not compile

更多资源

此页面的贡献者