kotlin類與物件 擴充套件

2022-07-02 21:15:07 字數 3610 閱讀 9302

1,擴充套件概念(oc中早期就有此功能)

kotlin 能夠擴充套件乙個類的新功能而無需繼承該類或者使用像裝飾者這樣的設計模式。這通過叫做 擴充套件 的特殊宣告完成。例如,你可以為乙個你不能修改的、來自第三方庫中的類編寫乙個新的函式。這個新 增的函式就像那個原始類本來就有的函式一樣,可以用普通的方法呼叫。這種機制稱為擴充套件函式此外,也有擴充套件屬性, 允許你為乙個已經存在的類新增新的屬性

2.擴充套件函式,宣告乙個擴充套件函式,我們需要用乙個 接收者型別 也就是被擴充套件的型別來作為他的字首。下面**為 mutablelist新增乙個 swap 函式:

fun mutablelist.swap(index1: int, index2: int) 

//這個 this 關鍵字在擴充套件函式內部對應到接收者物件(傳過來的在點符號前的物件)現在,我們對任意 mutablelist呼叫該函式了:

val list = mutablelistof(1, 2, 3

)list.swap(

0, 2) //

「swap()」內部的「this」會儲存「list」的值

//當然,這個函式對任何 mutablelist起作用,我們可以泛化它:

//為了在接收者型別表示式中使用泛型,我們要在函式名前宣告泛型引數

fun mutablelist.swap(index1: int, index2: int)

3.擴充套件是靜態解析的

擴充套件不能真正的修改他們所擴充套件的類。通過定義乙個擴充套件,你並沒有在乙個類中插入新成員,僅僅是可 以通過該型別的變數用點表示式去呼叫這個新函式。

我們想強調的是擴充套件函式是靜態分發的,即他們不是根據接收者型別的虛方法。這意味著呼叫的擴充套件函 數是由函式呼叫所在的表示式的型別來決定的,而不是由表示式執行時求值結果決定的。例如

open class

shape

class

rectangle : shape()

fun shape.getname() = "

shape

"fun rectangle.getname() = "

rectangle

"fun printclassname(s: shape)

printclassname(rectangle())

//這個例子會輸出 "shape",因為呼叫的擴充套件函式只取決於引數 s 的宣告型別,該型別是 shape 類

//如果乙個類定義有乙個成員函式與乙個擴充套件函式,而這兩個函式又有相同的接收者型別、相同的名字,並且都適用給定的引數,這種情況總是取成員函式。例如:

class

example

}fun example.printfunctiontype()

example().printfunctiontype()

//這段**輸出「class method」。

//當然,擴充套件函式過載同樣名字但不同簽名成員函式也完全可以

class

example

}fun example.printfunctiontype(i: int)

example().printfunctiontype(

1)

4.可空接收者

注意可以為可空的接收者型別定義擴充套件。這樣的擴充套件可以在物件變數上呼叫,即使其值為 null,並且可 以在函式體內檢測 this == null ,這能讓你在沒有檢測 null 的時候呼叫 kotlin 中的tostring():檢測發生在擴充套件函式的內部。

fun any?.tostring(): string

5.擴充套件屬性,與函式類似,kotlin 支援擴充套件屬性

val list.lastindex: int 

get() = size - 1

5.1 注意:由於擴充套件沒有實際的將成員插入類中,因此對擴充套件屬性來說幕後欄位是無效的。這就是為什麼擴 展屬性不能有初始化器。他們的行為只能由顯式提供的 getters/setters 定義

val house.number = 1

//錯誤:擴充套件屬性不能有初始化器

6.伴生物件的擴充套件,如果乙個類定義有乙個伴生物件 ,你也可以為伴生物件定義擴充套件函式與屬性。就像伴生物件的常規成員 一樣,可以只使用類名作為限定符來呼叫伴生物件的擴充套件成員:

class

myclass //

將被稱為 "companion"

}fun myclass.companion.printcompanion()

fun main()

7.擴充套件的作用域

//

大多數時候我們在頂層定義擴充套件⸺直接在包裡

package org.example.declarations

fun list

.getlongeststring()

7.1 要使用所定義包之外的乙個擴充套件,我們需要在呼叫方匯入它

package org.example.usage

import org.example.declarations.getlongeststring

fun main()

8.擴充套件宣告為成員

8.1 在乙個類內部你可以為另乙個類宣告擴充套件。在這樣的擴充套件內部,有多個 隱式接收者——其中的物件成員 可以無需通過限定符訪問。擴充套件宣告所在的類的例項稱為 分發接收者,擴充套件方法呼叫所在的接收者型別 的例項稱為 擴充套件接收者。

class

host(val hostname: string)

}class

connection(val host: host, val port: int)

fun host.printconnectionstring()

fun connect()

}fun main()

8.2 對於分發接收者與擴充套件接收者的成員名字衝突的情況,擴充套件接收者優先。要引用分發接收者的成員你可 以使用 限定的 this 語法。

class

connection

}}

8.3 宣告為成員的擴充套件可以宣告為 open 並在子類中覆蓋。這意味著這些函式的分發對於分發接收者型別 是虛擬的,但對於擴充套件接收者型別是靜態的

open class

base {}

class

derived : base() {}

open

class

basecaller

open fun derived.printfunctioninfo()

fun call(b: base)

}class

derivedcaller : basecaller()

override

fun derived.printfunctioninfo()

}fun main()

9.關於可見行的說明

擴充套件的可⻅性與相同作用域內宣告的其他實體的可⻅性相同。例如:

— 在檔案頂層宣告的擴充套件可以訪問同一檔案中的其他

private

頂層宣告;

— 如果擴充套件是在其接收者型別外部宣告的,那麼該擴充套件不能訪問接收者的

private 成員

kotlin類與物件初始

類就是某種事物,物件就是某種事物裡面的某個類,如人是乙個類,男人女人就是類裡面的物件 學校是乙個類,裡面的某個班級就是這個類裡面的某個物件 物件可以具有類的所有特徵,也可以有自己的特徵 比如,人可以吃飯,說話,唱歌,男人,女人都是同樣的,也都可以唱歌,吃飯,但是他們還可以談戀愛,吃零食,每個物件都有...

Kotlin 類和物件

android studio 3.3 類的修飾符 類屬性修飾符 abstract 抽象類 final 類不可繼承,預設屬性 enum 列舉類 open 類可繼承,類預設是final的 annotation 註解類 訪問許可權修飾符 private 僅在同乙個檔案中可見 protected 同乙個檔案...

kotlin 擴充套件

kotlin允許擴充套件類的屬性和方法,不需要繼承或使用 decorator 模式。擴充套件是一種靜態行為,對被擴充套件的類 本身不會造成任何影響。擴充套件函式定義形式 fun receivertype functionname params 其中,receivertype 為待擴充套件的類名,修飾...