您好,登錄后才能下訂單哦!
Scala語言通過 extends 關鍵字來繼承類.
那么繼承一個類有什么好處呢? 子類除了擁有繼承自超類的方法和字段(即為val(常量), var(變量)所定義的), 還可以添加自己需要的新方法和新字段, 而且不但可以重寫(override)超類的方法, 還可以重寫超類的字段
.
在Scala中, 不僅可以將類聲明為final, 而且可以將字段和方法聲明為final
當類被聲明為final時, 類不可以被繼承; 當方法和字段被聲明為final時, 對應的方法和字段不可以被子類重寫, 看看下面這個例子就一目了然
class Person { final val key = 0 val e = 1}class Kid extends Person { // 報錯: Value 'key' can not override final member // override val key = 1 override val e = 2 }object test extends App { val k = new Kid; println(k.key) println(k.e) }/*output02*/
在Scala中重寫一個非抽象方法必須
使用override
修飾符, 如:
override def toString: String = getClass.getName + "[name=" + name + "]"
override修飾符可以在多個常見的情況下給出有用的錯誤提示, 包括:
當你拼錯了要重寫的方法名和字段名
當你不小心在新方法中使用了錯誤的參數類型
當你在超類中引入了新方法, 而這個新方法和子類的方法抵觸
Scala語言使用super
關鍵字調用超類的方法, super.toString 相當于Person.toString
class Person { final val key = 0 val name = "person" val age = 1 override def toString: String = getClass.getName + "[name=" + name + "]"}class Kid extends Person { //override val key = 1 override val name = "kid" override val age = 2 override def toString: String = super.toString + "[age=" + age + "]"}object test extends App { val k = new Kid; println(k.key) println(k.age) println(k) }/*output02chap08.Kid[name=kid][age=2]*/
Scala語言中可以使用 isInstanceOf[T] 方法, 測試某個對象實際類型是否屬于某個給定類T或者類T的子類; 測試成功之后可以用 asInstanceOf[T] 方法將對象引用轉化為的(子類)類T引用(一般來說對象的引用類型是T的父類, 而實際類型是T或者T的子類)
if (kid.isInstanceOf[Kid]) { val s = kid.asInstanceOf[Kid] }
如果kid是null, 則 kid.isInstanceOf[Kid] 返回false, kid.asInstanceOf[Kid] 返回null, 如果kid不是一個Kid, kid.asInstanceOf[Kid]將拋出異常
如果要測試kid指向Kid類又不是其子類, 使用如下方法:
if (kid.getClass == classOf[Kid]) { val s = kid.asInstanceOf[Kid] }
類有一個主構造器和任意數量的輔助構造器, 而每個輔助構造器都必須以對先前定義的輔助構造器或者主構造器的調用開始, 這樣做的結果就是:
輔助構造器永遠都不可能
直接調用超類的構造器; 子類的輔助構造器最終都會調用主構造器; 只有主構造器而已調用超類的構造器.
主構造器是和類的定義交織在一起, 調用超類的構造器同樣也交織在一起
class Kid(gender: String, val height: Double) extends Person(gender)
Kid類有2個參數, 一個被"傳遞"到超類
scala語言的(主)構造器中, 你不能調用super(paras)
Scala的字段(Fields)由一個私有字段和取值器/改值器方法構成
你可以用一個同名的val字段重寫一個val或者不帶參數的def, 子類有一個私有字段和一個共有的getter方法, 而這個getter方法重寫了超類的getter方法.
class Smiler(val happy: String) { override def toString: String = getClass.getName + "[happy: " + happy + "]"}class Laughter(veryhappy: String) extends Smiler(veryhappy) { override val happy: String = "Laughter" override val toString: String = super.toString}
更常見的例子是 val 重寫抽象的 def,就像這樣:
abstract class Smiler(val happy: String) { def degree: Int}class Laughter(lhappy: String, override val degree: Int) extends Smiler(lhappy) { }
注意如下限制:
def 只能重寫另一個def
val 只能重寫另一個val或者不帶參數的def
var 只能重寫另一個抽象的var
你可以通過包含帶有定義或重寫的代碼塊的方式創建一個匿名子類,比如
val alien = new Person("good") { def greeting = "hi, good" }
不需要對抽象方法和抽象字段用abstract關鍵字
子類中重寫超類的抽象方法和抽象字段時, 不需要override
關鍵字
只要類中存在抽象方法, 該類必須聲明為 abstract
Scala中使用 abstract關鍵字來標記不能實例化的類, 通常是因為它的某個或者幾個方法沒有完整定義. 例如
abstract class Smiler(val happy: String) { def degree: Int}
在Scala中, 不需要對抽象方法用abstract關鍵字, 只是省去其方法體
只要類中存在抽象方法, 該類必須聲明為 abstract
子類重寫超類的抽象方法時, 不需要override關鍵字
class Laughter(lhappy: String) extends Smiler(lhappy) { def degree = lhappy.hashCode }
除了抽象方法外, 類還可以有抽象字段; 抽象字段就是一個沒有初始值的字段. 具體的子類必須提供具體的字段; 和方法一樣, 子類中重寫超類的抽象字段時, 不需要override
關鍵字
abstract class Abstract { val id: Int // 沒有初始化, 這是一個帶有getter方法的抽象字段 var name: String // 沒有初始化, 這是一個帶有getter和setting方法的抽象字段}class AbstractField(val id: Int) extends Abstract { var name = getClass.getName // override 可選}
可以隨時用匿名類型來定制抽象字段
val laught = new Abstract { val id = 10 var name = "laught" }
與Java基本類型相對應的類以及Unit類型(相當于Java的void)都擴展自AnyVal
所有其他類都是AnyRef的子類, Any是整個繼承層級的根節點, AnyVal和AnyRef擴展自Any類
Any類定義了isInstanceOf asInstanceOf方法, 以及用于相等性判斷和哈希碼方法, AnyVal并沒有追加方法, 只是所有值類型的一個標記
Null類型唯一的實例就是null, 你可以將null賦值給任何引用, 但不能賦值給值類型的變量, 舉例來說不能講Int賦值為null
Nothing類型沒有實例, 它對于泛型結構很有用, 比如說空列表Nil
是List[Nothing], 它是List[T]的子類型, T可以是任何類型
Scala中的Nothing類型和Java中void不是一個概念;
Scala中void由Unit類型表示, 該類型只有一個值, 那就是();
<<快學Scala>>中所說雖然Unit不是任何類型的超類, 但編譯器允許任何值來替換成(), 不過現在測試scala2.12.2, Scala已經修改這個語法, 現在不管傳入什么值, printUnit的輸出結果都是()
def printAny(x: Any) {print(x)}def printUnit(x: Unit) {print(x)}printAny("happy")printUnit("happy")/*output:happy()/*
Scala中調用 ==
, 如果比較的是引用類型, Scala會先做null
檢查, 然后調用equals
方法
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。