- 調(diào)用父類構(gòu)造函數(shù)
- 使用主構(gòu)造函數(shù)
- 使用此構(gòu)造函數(shù)重載
- 使用參數(shù)默認(rèn)值調(diào)用構(gòu)造函數(shù)
- 重寫成員屬性和函數(shù)
- 重寫成員屬性
- 重寫成員函數(shù)
??kotlin中類繼承只能是單繼承,但是卻可以有多個(gè)接口實(shí)現(xiàn)冗懦,這一點(diǎn)與 Java 是一致的哲鸳。kotlin中子類能夠繼承父類甚纲,那么父類需要聲明為 open露泊,在 kotlin 中默認(rèn)類不能被繼承尤泽,所以必須聲明為 open签杈。
一、調(diào)用父類構(gòu)造函數(shù)
??當(dāng)子類實(shí)例化時(shí)沽一,不僅需要初始化子類成員屬性盖溺,也需要初始化父類成員屬性,初始化父類成員屬性需要調(diào)用父類構(gòu)造函數(shù)铣缠。
open class Person(val name: String,
val age: Int,
val birthDate: Date) { // 主構(gòu)造函數(shù)
constructor(name: String, age: Int): this(name, age, Date()) // 次構(gòu)造函數(shù)
override fun toString(): String {
return ("Person [name=$name, age=$age, birthDate=$birthDate]")
}
}
1烘嘱、使用主構(gòu)造函數(shù)
class Student(name: String,
age: Int,
birthDate: Date,
val school: String): Person(name, age, birthDate) { // 主構(gòu)造函數(shù)
constructor(name: String, age: Int, school: String): this(name, age, Date(), school) //1??
// constructor(name: String, age: Int, school: String): super(name, age, Date()) 2??
constructor(name: String, school: String): this(name, 18, school)
}
??子類繼承父類時(shí),子類中一旦聲明了主構(gòu)造函數(shù)蝗蛙,那么子類的此構(gòu)造函數(shù)就不能直接調(diào)用父類構(gòu)造函數(shù)蝇庭,只能調(diào)用自己的主構(gòu)造函數(shù)。例如上述代碼第1??行只能調(diào)用this(name, age, Date(), school)
而不能調(diào)用super(name, age, Date())
捡硅,如第2??行代碼是編譯不通過的哮内。
2、使用此構(gòu)造函數(shù)重載
class Student: Person {
private var school: String? = null
constructor(name: String,
age: Int,
birthDate: Date,
school: String): super(name, age, birthDate) { // 3??
this.school = school
}
constructor(name: String,
school: String): super(name, 18) { // 4??
this.school = school
}
constructor(name: String, age: Int, school: String): this(name, age, Date(), school)
}
??子類繼承父類時(shí)壮韭,子類中如果沒有聲明主構(gòu)造函數(shù)北发,則子類的次構(gòu)造函數(shù)能直接調(diào)用父類構(gòu)造函數(shù),如代碼第3??行調(diào)用父類的主構(gòu)造函數(shù)喷屋,代碼第4??行調(diào)用父類的次構(gòu)造函數(shù)琳拨。
3、使用參數(shù)默認(rèn)值調(diào)用構(gòu)造函數(shù)
??一個(gè)類有多個(gè)構(gòu)造函數(shù)時(shí)屯曹,多個(gè)構(gòu)造函數(shù)之間構(gòu)成了重載關(guān)系狱庇,kotlin 從語法角度是支持重載的,但更推薦采用參數(shù)默認(rèn)值的方式恶耽。
class Student: Person {
private var school: String? = null
constructor(name: String,
age: Int = 18,
birthDate: Date = Date(),
school: String): super(name, age, birthDate) {
this.school = school
}
}
??這段代碼只有一個(gè)次構(gòu)造函數(shù)僵井,和4個(gè)參數(shù),其中 age 和 birthDate 提供了默認(rèn)值驳棱。這樣聲明相當(dāng)于提供了4個(gè)構(gòu)造函數(shù)批什。調(diào)用方式如下:
fun main(args: Array<String>) {
val student1 = Student("小三", 20, Date(), "清華大學(xué)")
val student2 = Student("小三", birthDate = Date(), school = "清華大學(xué)")
val student3 = Student("小三", school = "清華大學(xué)")
val student4 = Student("小三", age = 20, school = "清華大學(xué)")
}
??上面代碼只有一個(gè)次構(gòu)造函數(shù),起始也可以有一個(gè)主構(gòu)造函數(shù)社搅。
class Student(name: String,
age: Int = 18,
birthDate: Date = Date(),
school: String): Person(name, age, birthDate) {
private var school: String? = null
init {
this.school = school
}
}
二驻债、重寫成員屬性和函數(shù)
子類繼承父類后,子類中可能聲明了與父類一樣的成員屬性和函數(shù)形葬。
1合呐、重寫成語屬性
??子類成員屬性與父類一樣,就會(huì)重寫 (override) 父類中的成員屬性笙以,也就是屏蔽了父類成員屬性淌实。
open class ParentClass {
open var x: Int = 10
}
class SubClass: ParentClass() {
// 屏蔽父類x成員屬性
override var x: Int = 20
fun printX() {
println("x = $x") // 訪問的是SubClass的成員屬性x
println("super.x = ${super.x}") // 訪問ParentClass的成員屬性x
}
}
fun main(args: Array<String>) {
val subClass = SubClass()
subClass.printX()
}
// x = 20
// super.x = 10
??子類繼承父類時(shí),子類可以重寫父類總的成員屬性,默認(rèn)情況下屬性是不能被重寫的拆祈,它們需要聲明為 open恨闪。另外,在子類中要重寫屬性需要有 override 關(guān)鍵字聲明放坏。
??注意:由于子類重寫了父類的成員屬性咙咽,所以會(huì)造成父類的被重寫的成員屬性可見性被屏蔽,所以要想在子類中讓然使用父類被重寫的屬性淤年,需要通過關(guān)鍵字 super. 調(diào)用钧敞。
2、重寫成員函數(shù)
??如果子類函數(shù)完全與父類函數(shù)相同麸粮,即:相同的函數(shù)名溉苛、相同的參數(shù)列表和相同的返回類型,只是函數(shù)體不同弄诲,這稱為子類重寫父類函數(shù)炊昆。
open class ParentClass {
open var x: Int = 0
open fun setValue() {
x = 10 // 6??
}
}
class SubClass: ParentClass() {
// 屏蔽父類x成員屬性
override var x: Int = 0
public override fun setValue() {
x = 20
super.setValue()
}
fun display() {
println("x = $x")
println("super.x = ${super.x}")
}
}
fun main(args: Array<String>) {
val subClass = SubClass()
subClass.setValue()
subClass.display()
}
2019-05-31 11:19:32.687 5085-5085/cn.ak.kot I/System.out: x = 10
2019-05-31 11:19:32.687 5085-5085/cn.ak.kot I/System.out: super.x = 0
??重寫成員函數(shù) 與 重寫成員屬性 是一樣,同樣會(huì)屏蔽父類中被重寫函數(shù)的可見性威根;父類中函數(shù)同樣要聲明為 open 的,因?yàn)槟J(rèn)是 final 的视乐;子類重寫函數(shù)也一樣要使用關(guān)鍵字 override 修飾洛搀;在子類調(diào)用父類被重寫的函數(shù)一樣需要通過 super. 函數(shù)名。
??分析: main 函數(shù)中實(shí)例化的是 SubClass
類佑淀,所以 subClass.setValue()
調(diào)用的自然是 SubClass
的 setValue()
函數(shù)留美,而其中又通過 super.setValue()
調(diào)用了父類的 setValue()
,但注意代碼第6??行中的 x 是對應(yīng) SubClass 的 x 屬性伸刃,因?yàn)?ParentClass
的 x 屬性被重載導(dǎo)致可見性被屏蔽谎砾。所以最終結(jié)果是super.x = 0
。
??注意:重寫后的函數(shù)不能比原函數(shù)有更嚴(yán)格的可見性(可以相同)捧颅。