Scala/類
在 Scala 中,類是一種帶有成員的型別,例如欄位和方法。類例項可以使用值進行引數化,類可以使用型別進行引數化,這在Scala/型別引數中介紹。
一個簡單的類示例
class SimpleClass
val simple1 = new SimpleClass
val simple2 = new SimpleClass
在第一行,關鍵字 "class" 用於開始類定義。 "class" 後面是類名 "SimpleClass"。這定義了一個名為 "SimpleClass" 的類。在第二行,一個名為 "simple1" 的值被賦值為表示式 "new SimpleClass" 的結果。 "new" 關鍵字根據類名建立一個例項並返回對該例項的引用,"new SimpleClass" 建立一個 "SimpleClass" 型別的新的例項。在第三行,一個名為 "simple2" 的值被賦值為表示式 "new SimpleClass" 的結果,建立了另一個 "SimpleClass" 型別的新的例項。因此,名為 "simple1" 和 "simple2" 的值各自儲存對 "SimpleClass" 型別不同例項的引用。
類可以包含諸如欄位之類的成員
class FieldsClass {
val name = "SomeName"
var num = 0
}
在第一行,聲明瞭一個名為 "FieldsClass" 的類。在 "FieldsClass" 名字後面是 "{",它開始了類定義的主體。第二行聲明瞭一個欄位,在本例中是一個名為 "name" 的值,被賦值為字串 "SomeName"。第三行也聲明瞭一個欄位,在本例中是一個名為 "num" 的變數,被賦值為數字 '0'。第四行包含一個關閉的 "}",它結束了類定義的主體。
可以使用 "." 訪問類的成員
val fields1 = new FieldsClass
val fields2 = new FieldsClass
fields1.num = 3
fields2.num = 16
println("fields1.num is: " + fields1.num) //Prints "fields1.num is: 3".
println("fields2.num is: " + fields2.num) //Prints "fields2.num is: 16".
第一行和第二行聲明瞭兩個名為 "fields1" 和 "fields2" 的值,它們各自包含對 "FieldsClass" 例項的引用。第三行從 "fields1.num" 開始。"." 用於訪問例項的成員。"." 之前的表示式指定例項,"." 後的名稱指定成員。在本例中,指定的例項是 "fields1" 中引用的例項,指定的成員是欄位 "num"。在 "fields1.num" 後面是一個賦值,它使用數字 3,將數字 3 賦值給第一個 "FieldsClass" 例項中的 "num" 欄位。第四行與第三行類似,但數字 16 被賦值給第二個 "FieldsClass" 例項中的 "num" 欄位。第五行和第六行訪問兩個例項並列印它們 "num" 欄位的值,第一個例項的值為 3,第二個例項的值為 16。
類也可以有函式作為成員。這些函式被稱為方法
class Counter {
var count = 0
def incrementAndGet = {count += 1; count}
}
val counter1 = new Counter
println("Count is: " + counter1.count) //Prints "Count is: 0".
println("Count is: " + counter1.incrementAndGet) //Prints "Count is: 1".
println("Count is: " + counter1.count) //Prints "Count is: 1".
在第一行到第四行,定義了一個名為 "Counter" 的類。第三行定義了一個方法,就像定義一個函式一樣。在第五行,建立了一個新的 "Counter" 例項並賦值給名為 "counter1" 的值。
在第六行,列印例項的計數,即 0。在第七行,使用 "." 訪問 "Counter" 的 "incrementAndGet" 方法,就像訪問其他成員一樣,並呼叫它。注意,該方法在將計數加 1 後將計數賦值給 incrementAndGet,因此列印的例項計數為 1。在第八行,再次列印例項計數,給出增加後的值 1。
類例項可以使用建構函式透過值進行引數化。一個簡單的例子
class Circle(r:Double) {
def area = math.Pi * math.pow(r, 2)
}
val circle1 = new Circle(10.0)
val circle2 = new Circle(20.0)
println("Circle 1's area: " + math.round(circle1.area)) //Prints "Circle 1's area: 314".
println("Circle 2's area: " + math.round(circle2.area)) //Prints "Circle 2's area: 1257".
第一行開始宣告一個名為 "Circle" 的新類。在名字後面是 "(r:Double)",它定義了類的主要建構函式。主要建構函式包含一對圓括號,其中包含以逗號分隔的引數列表及其型別。在本例中,定義了一個名為 "r" 的引數,其型別為 "Double"。第二行定義了一個用於計算圓形面積的方法,該方法使用主要建構函式中定義的引數 "r",第三行結束了類定義。第四行定義了一個名為 "circle1" 的新值,並將其賦值為表示式 "new Circle(10.0)" 的結果。圓括號包含傳遞給 "Circle" 的主要建構函式的引數,在本例中為 "10.0"。因此,"circle1" 包含對 "Circle" 例項的引用,該例項使用 "r" 等於 "10.0" 進行引數化。第五行也是一樣的,除了 "circle2" 例項的 "r" 等於 "20.0"。在第六行和第七行,列印圓形的面積。
在類中宣告引數列表時,有三種限定符選項:無、"val" 和 "var"。如果沒有限定符,如前所述,只能在類內部訪問引數。如果限定符是 "val",則可以在類外部訪問引數,但不能對其賦值。如果限定符是 "var",則可以在類外部訪問引數,並且可以對其賦值。
在引數列表中使用 "val" 的示例
class Point(val x:Int, val y:Int, val z:Int)
val p1 = new Point(3, 10, -5)
println("p1's coordinates are: " + p1.x + ", " + p1.y + ", " + p1.z) //Prints "p1's coordinates are: 3, 10, -5".
在第一行中,所有引數都被 "val" 限定。在第二行中,構造了一個 "Point" 例項,在第三行中,在 "Point" 的定義之外訪問了 "Point" 例項的引數。
在引數列表中使用 "var" 的示例
class Accumulator(var sum:Int)
val accumulator1 = new Accumulator(30)
println("Sum is: " + accumulator1.sum) //Prints "Sum is: 30".
accumulator1.sum += 50
println("Sum is: " + accumulator1.sum) //Prints "Sum is: 80".
輔助建構函式是類的替代建構函式,在類中定義為名為 "this" 的方法。類可以有多個輔助建構函式,但它們應該具有不同的簽名,並且必須呼叫之前定義的建構函式。
class Car(val color:String,val year:Int)
{
def this(){
this("Black",2010) //Auxiliary constructor with defaults
}
def this(color:String) {
this(color,2010)
}
def this(year:Int){
this("Black",year)
}
}
object Car {
def main(args:Array[String])= {
//You can instantiate the Car with different constructor signatures
val blackCar = new Car()
val redCar = new Car("Red")
val defCar = new Car("Green", 2013)
val oldCar = new Car(1990)
}
}
在上面的示例中,我們有三個輔助建構函式。