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