- Kotlin 教程
- Kotlin - 首頁
- Kotlin - 概述
- Kotlin - 環境搭建
- Kotlin - 架構
- Kotlin - 基本語法
- Kotlin - 註釋
- Kotlin - 關鍵字
- Kotlin - 變數
- Kotlin - 資料型別
- Kotlin - 運算子
- Kotlin - 布林值
- Kotlin - 字串
- Kotlin - 陣列
- Kotlin - 範圍
- Kotlin - 函式
- Kotlin 控制流
- Kotlin - 控制流
- Kotlin - if...else 表示式
- Kotlin - when 表示式
- Kotlin - for 迴圈
- Kotlin - while 迴圈
- Kotlin - break 和 continue
- Kotlin 集合
- Kotlin - 集合
- Kotlin - 列表
- Kotlin - 集合
- Kotlin - 對映
- Kotlin 物件和類
- Kotlin - 類和物件
- Kotlin - 建構函式
- Kotlin - 繼承
- Kotlin - 抽象類
- Kotlin - 介面
- Kotlin - 可見性控制
- Kotlin - 擴充套件
- Kotlin - 資料類
- Kotlin - 密封類
- Kotlin - 泛型
- Kotlin - 委託
- Kotlin - 解構宣告
- Kotlin - 異常處理
- Kotlin 有用資源
- Kotlin - 快速指南
- Kotlin - 有用資源
- Kotlin - 討論
Kotlin - 繼承
繼承可以定義為一個類獲取另一個類的成員(方法和屬性)的過程。透過使用繼承,資訊以分層順序進行管理。
繼承其他類成員的類被稱為子類(派生類或子類),其成員被繼承的類被稱為超類(基類或父類)。
繼承是面向物件程式設計的關鍵特性之一,它允許使用者從現有類建立新類。透過繼承,我們可以繼承基類中的所有特性,並可以擁有自己的附加特性。
Kotlin 中的所有類都有一個共同的超類,稱為Any,它是未宣告任何超型別的類的預設超類。
class Example // Implicitly inherits from Any
Kotlin 超類Any 有三個方法:equals()、hashCode() 和 toString()。因此,這些方法為所有 Kotlin 類定義。
在 Kotlin 中,所有內容預設情況下都是final,因此,我們需要在類宣告前面使用關鍵字open 來使其可被其他類繼承。Kotlin 使用運算子":" 來繼承類。
示例
請看以下繼承示例。
open class ABC {
fun think () {
println("Hey!! i am thiking ")
}
}
class BCD: ABC(){ // inheritence happend using default constructor
}
fun main(args: Array<String>) {
var a = BCD()
a.think()
}
執行上述 Kotlin 程式後,將生成以下輸出
Hey!! i am thiking
重寫方法
現在,如果我們想在子類中重寫think()方法,那麼我們需要考慮以下示例,在這個示例中我們建立了兩個類並重寫了子類中的一個函式。
open class ABC {
open fun think () {
println("Hey!! i am thinking ")
}
}
class BCD: ABC() { // inheritance happens using default constructor
override fun think() {
println("I am from Child")
}
}
fun main(args: Array<String>) {
var a = BCD()
a.think()
}
執行上述 Kotlin 程式後,將生成以下輸出
I am from Child
用關鍵字override標記的成員本身是open的,因此可以在子類中重寫它。如果您想禁止再次重寫它,則必須將其設為final,如下所示
class BCD: ABC() {
final override fun think() {
println("I am from Child")
}
}
重寫屬性
重寫機制對屬性的工作方式與對方法的工作方式相同。在超類上宣告並在派生類上重新宣告的屬性必須以關鍵字override為字首,並且它們必須具有相容的型別。
open class ABC {
open val count: Int = 0
open fun think () {
println("Hey!! i am thinking ")
}
}
class BCD: ABC() {
override val count: Int
init{
count = 100
}
override fun think() {
println("I am from Child")
}
fun displayCount(){
println("Count value is $count")
}
}
fun main(args: Array<String>) {
var a = BCD()
a.displayCount()
}
執行上述 Kotlin 程式後,將生成以下輸出
Count value is 100
您還可以用var屬性重寫val屬性,反之則不行。這是允許的,因為val屬性實際上聲明瞭一個get方法,而將其重寫為var則在派生類中額外聲明瞭一個set方法。
我們還可以將override關鍵字用作主建構函式中屬性宣告的一部分。下面的示例使用主建構函式重寫count屬性,如果不向建構函式傳遞任何值,它將採用預設值400。
open class ABC {
open val count: Int = 0
open fun think () {
println("Hey!! i am thinking ")
}
}
class BCD(override val count: Int = 400): ABC() {
override fun think() {
println("I am from Child")
}
fun displayCount(){
println("Count value is $count")
}
}
fun main(args: Array<String>) {
var a = BCD(200)
var b = BCD()
a.displayCount()
b.displayCount()
}
執行上述 Kotlin 程式後,將生成以下輸出
Count value is 200 Count value is 400
派生類初始化順序
當我們建立派生類的物件時,建構函式初始化從基類開始。這意味著首先將初始化基類屬性,然後呼叫任何派生類建構函式,任何進一步的派生類也是如此。
這意味著當執行基類建構函式時,在派生類中宣告或重寫的屬性尚未初始化。
open class Base {
init{
println("I am in Base class")
}
}
open class Child: Base() {
init{
println("I am in Child class")
}
}
class GrandChild: Child() {
init{
println("I am in Grand Child class")
}
}
fun main(args: Array<String>) {
var a = GrandChild()
}
執行上述 Kotlin 程式後,將生成以下輸出
I am in Base class I am in Child class I am in Grand Child class
訪問超類成員
派生類中的程式碼可以使用super關鍵字直接呼叫其超類函式和屬性。
open class Base() {
open val name:String
init{
name = "Base"
}
open fun displayName(){
println("I am in " + this.name)
}
}
class Child(): Base() {
override fun displayName(){
super.displayName()
println("I am in " + super.name)
}
}
fun main(args: Array<String>) {
var a = Child()
a.displayName()
}
執行上述 Kotlin 程式後,將生成以下輸出
I am in Base I am in Base
重寫規則
如果子類從其直接超類繼承相同成員的多個實現,則它必須重寫此成員並提供其自己的實現。
這與從單個父類繼承成員的子類不同,在這種情況下,子類不必提供所有開放成員的實現。
open class Rectangle {
open fun draw() { /* ... */ }
}
interface Polygon {
fun draw() { /* ... */ } // interface members are 'open' by default
}
class Square() : Rectangle(), Polygon {
// The compiler requires draw() to be overridden:
override fun draw() {
super<Rectangle>.draw() // call to Rectangle.draw()
super<Polygon>.draw() // call to Polygon.draw()
}
}
從Rectangle和Polygon兩者繼承都可以,但它們都具有draw()方法的實現,因此您需要在Square中重寫draw()併為其提供單獨的實現以消除歧義。
測驗時間 (面試和考試準備)
答案:C
解釋
Kotlin 使用關鍵字open 使任何類或其成員可繼承。
問2 - 從 Kotlin 繼承的角度來看,哪個語句是正確的?
答案:D
解釋
從 Kotlin 繼承的角度來看,所有給定的語句都是正確的。
答案:C
解釋
關於在子類中訪問父類成員,給定的語句 A 和 B 是正確的。