- Kotlin類之資料類、密封類、內部類.md
阿新 • • 發佈:2018-12-11
資料類
1.宣告
data關鍵字
data class Leaf(val size: String,val color: String,val shape: String,val vein: Int)
2.資料類宣告條件
- 主建構函式最少要有一個引數
- 資料類的主構造器的所有引數必須標記為val或var
- 資料類不能是抽象類、open類、封閉類、內部類
- 資料類不能繼承自任何其他類(但可以實現介面)
3.訪問資料類的2種方法
- 和普通類一樣"物件名.資料名"
- 編譯器從主建構函式中宣告的屬性中匯出的成員方法componentN()函式群
data class Leaf(val size: String, val color: String,val shape: String,val vein: Int)
fun main(args: Array<String>) {
val leaf = Leaf("20","green","cicle",57)
val size = leaf.size
val color = leaf.color
val shape = leaf.shape
val vein = leaf.vein
println("大小:$size 顏色: $color 形狀 $shape 葉子數: $vein")
}
data class Leaf(val size: String,val color: String,val shape: String,val vein: Int)
fun main(args: Array<String>) {
val leaf = Leaf("20","green","cicle",57)
val(size,color,shape,vein) = leaf
println("大小:$size 顏色: $color 形狀 $shape 葉子數: $vein")
}
4.componentN()函式群
componentN函式群會按宣告順序對應於所有屬性
上面的程式碼我們可以看到結構出來的變臉可以直接拿來用,比如資料體Leaf中的size屬性,componentN函式群會按照資料體Leaf中屬性宣告的順序,從component1到component4和size、color、shape、及vein一一對應。
5.編輯器做的事
- 生成equals()函式與hasCode()函式
- 生成toString()函式,由類名(引數1 = 值1,引數2 = 值2,…)構成
- 由所定義的屬性自動生成component1()、component2()、…、componentN()函式,其對應於屬性的宣告順序。
- copy()函式。(Koltin要修改資料類的屬性,則使用其獨有的copy()函式。其作用就是:修改部分屬性,但是保持其他不變)
密封類
1. 什麼是受限的類繼承結構
- 所謂受限的類繼承結構,即當類中的一個值只能是有限的幾種型別,而不能是其他的任何型別。
- 這種受限的類繼承結構從某種意義上講,它相當於是列舉類的擴充套件。但是,我們知道Kotlin的列舉類中的列舉常量是受限的,因為每一個列舉常量只能存在一個例項
- 但是其和列舉類不同的地方在於,密封類的一個子類可以有可包含狀態的多個例項。
- 也可以說成,密封類是包含了一組受限的類集合,因為裡面的類都是繼承自這個密封類的。但是其和其他繼承類(open)的區別在,密封類可以不被此檔案外被繼承,有效保護程式碼。但是,其密封類的子類的擴充套件是是可以在程式中任何位置的,即可以不在同一檔案下
2.宣告
sealed class SealedExpr()
內部類(巢狀類)
在實際開發中,用到內部類的地方是很多的。比如說:
- 對於Android開發來說,列表介面卡中的ViewHolder類就是一個內部類
- 根據後臺開發人員提供的json字串生成的物件中,也包含另外一個物件,這也是一個內部類
1.巢狀類
上面提到的兩種情況,是在開發中最常見的。當然說到內部類,就必須提到另一個概念,巢狀類,所謂巢狀類:即指一個類可以巢狀在其他類中。
例如:
class Other{ // 外部類
val numOuther = 1
class Nested { // 巢狀類
fun init(){
println("執行了init方法")
}
}
}
fun main(args: Array<String>) {
Other.Nested().init() // 呼叫格式為:外部類.巢狀類().巢狀類方法/屬性
}
注意
- 呼叫巢狀類的屬性或者方法格式為: 外部類.巢狀類().巢狀類方法/屬性。在呼叫的時候巢狀類是需要例項化的。
- 巢狀類不能使用外部類的屬性和成員
2.內部類
宣告一個內部類使用inner關鍵字。 宣告格式:inner class 類名(引數){}
class Other{ // 外部類
val numOther = 1
inner class InnerClass{ // 巢狀內部類
val name = "InnerClass"
fun init(){
println("我是內部類")
}
}
}
fun main(args: Array<String>) {
Other().InnerClass().init() // 呼叫格式為:外部類().內部類().內部類方法/屬性
}
*注意
- 呼叫內部類的屬性或方法的格式為:外部類().內部類().內部類方法/屬性。在呼叫的時候巢狀類是需要例項化的。
- 內部類不能使用外部類的屬性和成員
匿名內部類
作為一名Android開發者,對匿名內部類都不陌生,因為在開發中,匿名內部類隨處可見。比如說Button的OnClickListener,ListView的單擊、長按事件等都用到了匿名內部類。 一般的使用方式為定義一個介面,在介面中定義一個方法。
class Other{
lateinit private var listener : OnClickListener
fun setOnClickListener(listener: OnClickListener){
this.listener = listener
}
fun testListener(){
listener.onItemClick("我是匿名內部類的測試方法")
}
}
interface OnClickListener{
fun onItemClick(str : String)
}
fun main(args: Array<String>){
// 測試匿名內部類
val other = Other()
other.setOnClickListener(object : OnClickListener{
override fun onItemClick(str: String) {
// todo
println(str)
}
})
other.testListener()
}
內部類和繼承的區別
- 從宣告類上看,繼承的兩個類單獨宣告,子類通過(子類:父類)繼承父類,而內部類必須宣告在外部類裡面,並且用關鍵字inner標記
- 從訪問上看,繼承的父類不能直接訪問子類,外部類可以通過“外部類().內部類()”訪問內部類,繼承的子類能直接訪問父類公開的成員屬性及方法,而內部類值能通過[email protected]外部類的方式訪問外部類的屬性和方法
- 從能否覆蓋上看,繼承的子類能覆蓋父類用open標記的屬性和方法,內部類不能覆蓋外部類的屬性和方法
- 從定義物件的方法看,繼承的子類定義為val/var son = Son(),內部類的定義為 val/var inter = Outer().Inter()