本人也是在初學(xué)Kotlin,如有錯誤,請幫忙指出,持續(xù)更新
Android:Kotlin詳細(xì)入門學(xué)習(xí)指南-類和對象-基礎(chǔ)語法(四)
建議先看看前面的文章
Android:Kotlin詳細(xì)入門學(xué)習(xí)指南-基礎(chǔ)語法(一)
Android:Kotlin詳細(xì)入門學(xué)習(xí)指南-基本類型-基礎(chǔ)語法(二)
Android:Kotlin詳細(xì)入門學(xué)習(xí)指南-包-控制流-返回與跳轉(zhuǎn)-基礎(chǔ)語法(三)
這篇文章分享的內(nèi)容比較多,建議先關(guān)注收藏,再查看,以免迷路
類和對象
- 類和繼承
- 屬性和字段
- 接口
- 可見性修飾詞
- 擴(kuò)展
- 數(shù)據(jù)對象
- 泛型
- 嵌套類
- 枚舉類
- 對象表達(dá)式和聲明
- 委派模式
- 委派屬性
類和繼承
類
在 Kotlin 中類用 class 聲明:
class Invoice { }
類的聲明包含類名,類頭(指定類型參數(shù),主構(gòu)造函數(shù)等等),以及類主體,用大括 號包裹。類頭和類體是可選的;如果沒有類體可以省略大括號。
構(gòu)造函數(shù)
Kotlin的構(gòu)造函數(shù)和java的還是有點區(qū)別
在 Kotlin 中類可以有一個主構(gòu)造函數(shù)以及多個二級構(gòu)造函數(shù)。主構(gòu)造函數(shù)是類頭的 一部分:跟在類名后面(可以有可選的類型參數(shù))。
class Person constructor(firstName: String) { }
如果主構(gòu)造函數(shù)沒有注解或可見性說明,則 constructor 關(guān)鍵字是可以省略:
class Person(firstName: String){ }
主構(gòu)造函數(shù)不能包含任意代碼。初始化代碼可以放在以 init 做前綴的初始化塊內(nèi)
class Customer(name: String) {
init {
logger,info("Customer initialized with value ${name}")
}
}
注意主構(gòu)造函數(shù)的參數(shù)可以用在初始化塊內(nèi),也可以用在類的屬性初始化聲明處:
class Customer(name: String) {
val customerKry = name.toUpperCase()
}
聲明屬性并在主構(gòu)造函數(shù)中初始化,在 Kotlin 中有更簡單的語法
class Person(val firstName: String, val lastName: String, var age : Int) { }
在主構(gòu)造函數(shù)中的屬性可以是可變的( var )或只讀的( val )。 如果構(gòu)造函數(shù)有注解或可見性聲明,則 constructor 關(guān)鍵字是不可少的
二級構(gòu)造函數(shù)
類似java的重載
類也可以有二級構(gòu)造函數(shù),需要加前綴 constructor :
class Person {
constructor(parent: Person) {
parent.children.add(this)
}
}
如果類有主構(gòu)造函數(shù),每個二級構(gòu)造函數(shù)都要,或直接或間接通過另一個二級構(gòu)造 函數(shù)代理主構(gòu)造函數(shù)。在同一個類中代理另一個構(gòu)造函數(shù)使用 this 關(guān)鍵字:
class Person(val name: String) {
constructor (name: String, paret: Person) : this(name) {
parent.children.add(this)
}
}
如果一個非抽象類沒有聲明構(gòu)造函數(shù)(主構(gòu)造函數(shù)或二級構(gòu)造函數(shù)),它會產(chǎn)生一個 沒有參數(shù)的構(gòu)造函數(shù)。該構(gòu)造函數(shù)的可見性是 public 。如果你不想你的類有公共的 構(gòu)造函數(shù),你就得聲明一個擁有非默認(rèn)可見性的空主構(gòu)造函數(shù):
class DontCreateMe private constructor () { }
注意:在 JVM 虛擬機(jī)中,如果主構(gòu)造函數(shù)的所有參數(shù)都有默認(rèn)值,編譯器會 生成一個附加的無參的構(gòu)造函數(shù),這個構(gòu)造函數(shù)會直接使用默認(rèn)值。這使得 Kotlin 可以更簡單的使用像 Jackson 或者 JPA 這樣使用無參構(gòu)造函數(shù)來創(chuàng)建類 實例的庫。
創(chuàng)建類的實例
val invoice = Invoice()
val customer = Customer("Joe Smith")
注意 Kotlin 沒有 new 關(guān)鍵字。
內(nèi)部類要使用inner關(guān)鍵字。
類成員
類可以包含:
- 構(gòu)造函數(shù)和初始化代碼塊
- 函數(shù)
- 屬性
- 內(nèi)部類
- 對象聲明
繼承
Kotlin 中所有的類都有共同的父類 Any ,java是Obejct,它是一個沒有父類聲明的類的默認(rèn)父 類:
Any 不是 java.lang.Object ;事實上它除了 equals() , hashCode() 以 及 toString() 外沒有任何成員了。
聲明一個明確的父類,需要在類頭后加冒號再加父類
open class Base(p: Int)
class Derived(p: Int) : Base(p)
普通的類如果需要被繼承就需要有open關(guān)鍵字
open 注解與java中的 final 相反:它允許別的類繼承這個類。默認(rèn)情形下,kotlin 中所有的類都是 final
復(fù)寫方法
open class Base {
open fun v() {}
fun nv() {} }
class Derived() : Base() {
override fun v() {}
}
對于 Derived.v() 來說 override 注解是必須的。如果沒有加的話,編譯器會 提示。如果沒有 open 注解,像 Base.nv() ,在子類中聲明一個同樣的函數(shù)是不 合法的,要么加 override 要么不要復(fù)寫。在 final 類(就是沒有open注解的類) 中, open 類型的成員是不允許的。
普通方法標(biāo)記open,可被重寫
復(fù)寫屬性
復(fù)寫屬性與復(fù)寫方法類似,在一個父類上聲明的屬性在子類上被重新聲明,必須添 加 override ,并且它們必須具有兼容的類型。每個被聲明的屬性都可以被一個帶 有初始化器的屬性或帶有g(shù)etter方法的屬性覆蓋
復(fù)寫規(guī)則
在 kotlin 中,實現(xiàn)繼承通常遵循如下規(guī)則:如果一個類從它的直接父類繼承了同一 個成員的多個實現(xiàn),那么它必須復(fù)寫這個成員并且提供自己的實現(xiàn)(或許只是直接用 了繼承來的實現(xiàn))。為表示使用父類中提供的方法我們用 super<Base> 表示:
open class A {
open fun f () {
print("A")
}
fun a() {
print("a")
}
}
interface B {
fun f() {
print("B")
} // 接口的成員變量默認(rèn)是 open 的
fun b() {
print("b")
}
}
class C() : A() , B {
// 編譯器會要求復(fù)寫f()
override fun f() {
super<A>.f() // 調(diào)用 A.f()
super<B>.f() // 調(diào)用 B.f()
}
}
可以同時從 A 和 B 中繼承方法,而且 C 繼承 a() 或 b() 的實現(xiàn)沒有任何問題,因為 它們都只有一個實現(xiàn)。但是 f() 有倆個實現(xiàn),因此我們在 C 中必須復(fù)寫 f() 并且提供 自己的實現(xiàn)來消除歧義。
這次就先分享到這里,下次再繼續(xù)分享。