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 的值。請注意 setter 的特殊語法:方法在 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

更多資源

此頁面的貢獻者