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
類別有四個成員:變數 x
和 y
以及方法 move
和 toString
。與許多其他語言不同,主建構函式在類別簽章 (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
類別中, x
和 y
有預設值 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 x
和 def y
用於存取私有資料。 def x_=
和 def y_=
用於驗證和設定 _x
和 _y
的值。請注意 setter 的特殊語法:方法在 getter 的識別碼後附加 _=
,而參數在之後。
具有 val
和 var
的主建構函式參數是公開的。然而,由於 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
沒有 val
或 var
的參數是私有值,僅在類別內可見。
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
更多資源
- 在 Scala Book 中深入了解類別
- 如何使用 輔助類別建構函式