類的繼承
在Scala中讓子類繼承父類與Java一樣也是使用extends關(guān)鍵字吹散。繼承就代表子類可以從父類繼承父類的field和method弧械;子類可以在自己內(nèi)部放入父類所沒有子類特有的field和method;使用繼承可以有效復(fù)用代碼空民。
子類可以覆蓋父類的field和method刃唐;但是用final修飾的class無法被繼承的,field和method無法被覆蓋袭景。
定義父類
/**
* 定義人種抽象類
* 只要存在一個抽象方法即為abstract class唁桩。
*/
abstract class Human(val lang:String,val skin:String="黃色"){
val lang = lang
val skin = skin
print("這是在主構(gòu)造器中的代碼")
//自我介紹,抽象方法
def intro(nationality : String="Chinese") : Unit
}
定義子類
/**
* 定義黃種人
*
*/
class YellowRace(lang:String="Chinese",skin:String="黃色") extends Human(lang,skin){
...
}
重寫
重寫字段或者類的屬性耸棒、方法的時候使用override關(guān)鍵字荒澡。子類覆蓋父類方法之后,在子類中要調(diào)用父類的被覆蓋的方法時使用super關(guān)鍵字与殃,顯式地指定要調(diào)用父類的方法单山。
重寫方法
override def intro(nationality : String) : Unit = {
println("我是" + skin + "人種,我說" + lang+",我來自"+nationality)
}
重寫字段field
Scala中幅疼,子類可以覆蓋父類的val field米奸,而且子類的val field還可以覆蓋父類的val field的getter方法;只要在子類中使用override關(guān)鍵字即可爽篷。
val lang:String = "英語"
val skin:String = "白色"
類型判斷
isInstanceOf 和 asInstanceOf
如果創(chuàng)建了子類的對象悴晰,又將其賦予了父類類型的變量,則在后續(xù)的程序中需要將父類類型的變量轉(zhuǎn)換為子類類型的變量,應(yīng)該如何做铡溪?首先使用isInstanceOf判斷對象是否是指定類的對象胚鸯,如果是的話刑桑,則可以使用asInstanceOf將對象轉(zhuǎn)換為指定類型伪很。
如果對象是null毛甲,則isInstanceOf一定返回false,asInstanceOf一定返回null哈扮; 如果沒有用isInstanceOf先判斷對象是否為指定類的實(shí)例纬纪,就直接用asInstanceOf轉(zhuǎn)換,則可能會拋出異常
val chinese : Human = new Chinese
val zgr : Chinese = null
if(chinese.isInstanceOf[Chinese]) zgr = chinese.asInstanceOf[Chinese]
getClass 和classOf
isInstanceOf只能判斷出對象是否是指定類以及其子類的對象滑肉,而不能精確判斷出對象就是指定類的對象包各。如果要求精確地判斷對象就是指定類的對象那么就只能使用getClass和classOf了。對象.getClass可以精確獲取對象的類赦邻,classOf[類]可以精確獲取類髓棋,然后使用==操作符即可判斷
if(chinese.getClass == classOf[Chinese]) zgr = chinese.asInstanceOf[Chinese]
模式匹配
這種方式更加地簡潔明了,而且代碼得可維護(hù)性和可擴(kuò)展性也非常的高惶洲。使用模式匹配功能性上來說與isInstanceOf一樣按声,也是判斷主要是該類以及該類的子類的對象即可,不是精準(zhǔn)判斷的恬吕。
val chinese : Human = new Chinese
chinese match{
case c:Chinese=>...
case _ =>
}
protected
跟java一樣scala中同樣可以使用protected關(guān)鍵字來修飾field和method签则,這樣在子類中就不需要super關(guān)鍵字,直接就可以訪問field和method;還可以使用protected[this]铐料,則只能在當(dāng)前子類對象中訪問父類的field和method渐裂,無法通過其他子類對象訪問父類的field和method。
調(diào)用父類的構(gòu)造方法
Scala中每個類可以有一個主constructor和任意多個輔助constructor钠惩,而每個輔助constructor的第一行都必須是調(diào)用其他輔助constructor或者是主constructor柒凉;因此子類的輔助constructor是一定不可能直接調(diào)用父類的constructor的,只能在子類的主constructor中調(diào)用父類的constructor篓跛。如果是父類中接收的參數(shù)子類中接收時就不要用任何val或var來修飾了膝捞,否則會認(rèn)為是子類要覆蓋父類的field。
abstract class Human(lang:String,skin:String="黃色")
class YellowRace(lang:String="Chinese",skin:String="黃色") extends Human(lang,skin){
...
}
抽象類
如果在父類中有某些方法無法立即實(shí)現(xiàn)愧沟,需要依賴不同的子來來覆蓋蔬咬,重寫實(shí)現(xiàn)自己不同的方法實(shí)現(xiàn)。此時可以將父類中的這些方法不給出具體的實(shí)現(xiàn)沐寺,只有方法簽名林艘,這種方法就是抽象方法。一個類中如果有一個抽象方法混坞,那么類就必須用abstract來聲明為抽象類狐援,此時抽象類是不可以實(shí)例化的。在子類中覆蓋抽象類的抽象方法時,不需要使用override關(guān)鍵字咕村。
/**
* 定義人種抽象類
* 只要存在一個抽象方法即為abstract class场钉。
*/
abstract class Human(lang:String,skin:String="黃色"){
val lang = lang
val skin = skin
print("這是在主構(gòu)造器中的代碼")
//自我介紹蚊俺,抽象方法
def intro(nationality : String="Chinese") : Unit
}
創(chuàng)建類對象及方法的使用
//使用構(gòu)造方法中的默認(rèn)參數(shù)或者傳入明確的參數(shù)值
val chinese = new Chinese()
//調(diào)用自我介紹方法
chinese.inftro("中國")