本章將介紹如何在Scala編程中使用類和對(duì)象。類是對(duì)象的藍(lán)圖(或叫模板)。定義一個(gè)類后,可以使用關(guān)鍵字new
來創(chuàng)建一個(gè)類的對(duì)象。 通過對(duì)象可以使用定義的類的所有功能。
下面的圖通過一個(gè)包含成員變量(name
和 rollNo
)和成員方法(setName()
和setRollNo()
)的Student
類的例子來演示類和對(duì)象。最后都是類的成員。類是一個(gè)模板的東西,而對(duì)象是真實(shí)存在的。 在下圖中,Student
是一個(gè)類,而具體學(xué)生:Harini, John, 和 Maria 是學(xué)生類的對(duì)象,這此對(duì)象有是名字和注冊(cè)號(hào)。
以下是在Scala
中定義類的簡(jiǎn)單語法。這個(gè)類定義了兩個(gè)變量x
和y
以及一個(gè)move
方法,它沒有返回值。
使用類的名稱作為一個(gè)類構(gòu)造函數(shù),構(gòu)造函數(shù)可以使用多個(gè)參數(shù)。 上面的代碼定義了兩個(gè)構(gòu)造函數(shù)參數(shù)xc
和yc
; 它們?cè)陬惖恼麄€(gè)定義中都是可見的。
語法
class Point(xc: Int, yc: Int) {
var x: Int = xc
var y: Int = yc
def move(dx: Int, dy: Int) {
x = x + dx
y = y + dy
println ("Point x location : " + x);
println ("Point y location : " + y);
}
}
如本章前面所述,您可以使用關(guān)鍵字new
來創(chuàng)建對(duì)象,然后訪問類字段和方法,如下例所示:
import java.io._
class Point(val xc: Int, val yc: Int) {
var x: Int = xc
var y: Int = yc
def move(dx: Int, dy: Int) {
x = x + dx
y = y + dy
println ("Point x location : " + x);
println ("Point y location : " + y);
}
}
object Demo {
def main(args: Array[String]) {
val pt = new Point(10, 20);
// Move to a new location
pt.move(10, 10);
}
}
將上述程序保存在Demo.scala中,并使用以下命令編譯和執(zhí)行此程序。
D:\software\scala-2.12.3\bin>scalac Demo.scala
D:\software\scala-2.12.3\bin>scala Demo
Point x location : 20
Point y location : 30
D:\software\scala-2.12.3\bin>
在Scala中,我們可以擴(kuò)展一個(gè)Scala類,使用與Java中相同的方式設(shè)計(jì)繼承的類(使用extends
關(guān)鍵字),但有兩個(gè)限制:方法重寫需要override
關(guān)鍵字,只有主構(gòu)造函數(shù)可以通過參數(shù)調(diào)用基類構(gòu)造函數(shù)。讓我們擴(kuò)展上面的類,并增加一個(gè)類的方法。
例子
讓我們使用兩個(gè)類Point
作為一個(gè)例子(與上面一樣)和Location
類,Location
類是一個(gè)使用extends
關(guān)鍵字創(chuàng)建的繼承類。 這樣的“擴(kuò)展”子句有兩個(gè)效果:它使得Location
類從Point
類繼承所有非私有成員,并且使類型Location
成為Point
類類型的子類型。 所以Point
類被稱為超類(父類),Location
類被稱為子類。擴(kuò)展一個(gè)類并繼承父類的所有功能稱為繼承,但Scala允許只從一個(gè)類繼承(不支持多繼承)。
注意 - 在
Point
類中的move()
方法和Location
類中的move()
方法不會(huì)覆蓋move
的相應(yīng)定義,因?yàn)樗鼈兪遣煌亩x(例如,前者采用兩個(gè)參數(shù),后者采用三個(gè)參數(shù))。
參考以下示例程序來實(shí)現(xiàn)繼承 -
import java.io._
class Point(val xc: Int, val yc: Int) {
var x: Int = xc
var y: Int = yc
def move(dx: Int, dy: Int) {
x = x + dx
y = y + dy
println ("Point x location : " + x);
println ("Point y location : " + y);
}
}
class Location(override val xc: Int, override val yc: Int,
val zc :Int) extends Point(xc, yc){
var z: Int = zc
def move(dx: Int, dy: Int, dz: Int) {
x = x + dx
y = y + dy
z = z + dz
println ("Point x location : " + x);
println ("Point y location : " + y);
println ("Point z location : " + z);
}
}
object Demo {
def main(args: Array[String]) {
val loc = new Location(10, 20, 15);
// Move to a new location
loc.move(10, 10, 5);
}
}
將上述程序保存在源文件:Demo.scala中,并使用以下命令編譯和執(zhí)行此程序,輸出結(jié)果如下 -
D:\software\scala-2.12.3\bin>scalac Demo.scala
D:\software\scala-2.12.3\bin>scala Demo
Point x location : 20
Point y location : 30
Point z location : 20
D:\software\scala-2.12.3\bin>
當(dāng)類在范圍內(nèi)時(shí),隱式類允許與類的主構(gòu)造函數(shù)進(jìn)行隱式對(duì)話。隱式類是一個(gè)標(biāo)有'implicit'
關(guān)鍵字的類。此功能在Scala 2.10中引入。
語法 - 以下是隱式類的語法。這里,隱式類始終位于對(duì)象范圍內(nèi),所有方法定義都被允許,因?yàn)殡[式類不能是頂級(jí)類。
語法
object <object name> {
implicit class <class name>(<Variable>: Data type) {
def <method>(): Unit =
}
}
例子
下面演示如何使用隱式類,創(chuàng)建一個(gè)名稱為IntTimes的隱式類,并定義一個(gè)times()
方法。times()
包含一個(gè)循環(huán)事務(wù),它將按給定的次數(shù)執(zhí)行語句。假設(shè)要執(zhí)行4
次println(“”Hello“)
語句。
以下是示例程序代碼。在這個(gè)例子中,使用了兩個(gè)對(duì)象類(Run 和 Demo),將這兩個(gè)類保存在不同的文件中,名稱如下 -
Run.scala - 將以下程序保存在源文件:Run.scala 中
object Run {
implicit class IntTimes(x: Int) {
def times [A](f: =>A): Unit = {
def loop(current: Int): Unit =
if(current > 0){
f
loop(current - 1)
}
loop(x)
}
}
}
Demo.scala - 將以下程序保存在源文件:Demo.scala 中 -
import Run._
object Demo {
def main(args: Array[String]) {
4 times println("hello")
}
}
用于以下命令編譯和執(zhí)行這兩個(gè)程序,輸出結(jié)果如下 -
D:\software\scala-2.12.3\bin>scalac Demo.scala
D:\software\scala-2.12.3\bin>scala Demo
hello
hello
hello
hello
D:\software\scala-2.12.3\bin>
注 -
Scala比Java更面向?qū)ο?,因?yàn)樵赟cala中不能擁有靜態(tài)成員,Scala它使用單例對(duì)象。單例是一種只能有一個(gè)實(shí)例的對(duì)象。使用object
關(guān)鍵字對(duì)象而不是類關(guān)鍵字創(chuàng)建單例。由于無法實(shí)例化單例對(duì)象,因此無法將參數(shù)傳遞給主構(gòu)造函數(shù)。下面列出Scala使用單例對(duì)象的所有示例。
以下是實(shí)現(xiàn)單例的示例程序 -
import java.io._
class Point(val xc: Int, val yc: Int) {
var x: Int = xc
var y: Int = yc
def move(dx: Int, dy: Int) {
x = x + dx
y = y + dy
}
}
object Demo {
def main(args: Array[String]) {
val point = new Point(10, 20)
printPoint
def printPoint{
println ("Point x location : " + point.x);
println ("Point y location : " + point.y);
}
}
}
將上述程序保存在源文件:Demo.scala 中,使用以下命令編譯和執(zhí)行此程序,輸出結(jié)果如下 -
D:\software\scala-2.12.3\bin>scalac Demo.scala
D:\software\scala-2.12.3\bin>scala Demo
Point x location : 10
Point y location : 20