用途
抽象類別的最主要用途,就是禁止由此類別產生出物件。
假設有一個class Pokemon(神奇寶貝),仔細想一下,在主程式裏產生一個Pokemon的物件,這有意義嗎? 也就是說,產生出來的物件,其長像是圓是扁的呢? 神奇寶貝只是所有怪獸的統稱,它只是一個名詞而以。
如果產生一隻Pikachu(皮卡丘),或產生一隻Eve(伊布),我們都可以想像出它長的是什麼樣子。但是產生一隻Pokemon,到底是長啥樣子!! 所以產生Pokemon是沒有任何意義的。
如何禁止使用者產生Pokemon呢? 很簡單,加上 abstract即可
fun main(args:Array<String>){
var p=Pokemon()//此行錯誤,因為無法由抽象類別產生物件
}
abstract class Pokemon{
}
子類別繼承
子類別繼承抽象類別後,才可以產生物件。由下面的範例可以看出,把Pikachu及Eve相同的屬性置於父類別Pokemon之中,這是一般父子的關係,跟一般類別一樣,只差在父類別不能產生物件而以。
fun main(args:Array<String>){
var p=Pikachu(10)
var e=Eve(2)
}
abstract class Pokemon{
var level:Int=1
}
class Pikachu:Pokemon{
constructor(l:Int){
println("產生皮卡丘")
level=l
}
}
class Eve:Pokemon{
constructor(l:Int){
println("產生伊布")
level=l
}
}
製定遵守的契約
到目前為止,都跟一般類別差不多。接下來抽象類別可以製定繼承者必需遵守的契約。如下的Pokemon,有一個抽象方法 abstract fun food(),還有一個實體的方法 fun move()。
抽象方法就是父類別所規定必需實作的契約,子類別想要繼承父類別,就必需實作父類別的抽象方法。
fun main(args:Array<String>){
var p=Pikachu()
p.food("雜食")
p.move()
}
abstract class Pokemon{
var level:Int=1
abstract fun food(f:String) //抽象方法, 一定是 open
fun move(){//實體方法
println("用跑的")
}
}
class Pikachu():Pokemon(){
override fun food(a:String){
println("food : %s".format(a))
}
}
有幾個重點需背起來
1. 抽象類別不一定要有抽象方法,也可以抽象方法及實體方法同時存在。
2. 抽象方法是要給子類別實作的,所以一定是 open
3. 子類別繼承抽象類別後,一定要實作父類別的抽象方法,而且方法前面要加 override
4. 子類別若不實作抽象方法,那麼子類別也必需是抽象類別。