1. 程式人生 > >(二)Kotlin 面向物件

(二)Kotlin 面向物件

文章目錄

一、面向物件的概念

  • 本質上就是解決如何用程式描述世界的問題
  • 討論如何把實際存在的東西對映成程式的類和物件
  • 一種程式設計的思路、思想、方法
  • 程式設計層面的概念
  • 設計模式:前人的程式設計經驗

二、抽象類與介面

相當於半成品與協議

1、介面

  • 介面,直觀理解就是一種約定
interface InputDevice{
    fun input(event: Any)
}
  • 介面不能有狀態
  • 必須由類對其進行實現後使用

2、抽象類

  • 實現了一部分協議的半成品
  • 可以有狀態,可以有方法實現
  • 必須由子類繼承後使用

3、抽象類和介面的共性

  • 比較抽象,不能直接例項化
  • 需要有子類(實現類)實現的方法
  • 父類(介面)變數可以接受子類(實現類)的賦值

3、抽象類和介面的區別

  • 抽象類有狀態,介面沒有狀態
  • 抽象類有方法實現,介面只能有無狀態的預設實現
  • 抽象類只能單繼承,介面可以多實現
  • 抽象類反應本質,介面體現能力

三、類的繼承與介面的實現

  • 父類需要 open 才可以被繼承
  • 父類方法、屬性需要 open 才可以倍複寫
  • 介面、介面方法、抽象類預設為 open
  • 複寫父類(介面)成員需要 override 關鍵字
  • class D:A(),B,C
  • 注意繼承類時實際上呼叫了父類構造方法
  • 類只能單繼承,介面可以多實現

介面代理

  • class Manager(driver: Driver):Driver by driver
  • 介面方法實現交給代理類實現

介面方法衝突

- 介面方法可以有預設實現
- 簽名一致且返回值相同的衝突
- 子類(實現類)必須複寫衝突方法
- super<[父類(介面)名]>.[方法名]([引數列表])

四、類及其成員的可見性

Kotlin Java
private private
protected protected
default(包內可見)
internal(模組內可見)
public public

五、object

  • 只有一個例項的類(單例)
  • 不能自定義構造方法
  • 可以實現介面、繼承父類
  • 本質上就是單例模式最基本的實現

六、伴生物件與靜態成員

  • 每個類可以對應一個伴生物件
  • 伴生物件的成員全域性獨一份
  • 伴生物件的成員類似Java的靜態成員
  • 靜態成員考慮用包級函式、變數代替
  • 使用JvmField和JvmStatic,可以讓伴生物件在Java中使用時看起來像靜態成員和靜態方法

七、方法過載(Overloads)和預設引數

過載
  • 寫了一個方法和已經存在的方法重名,引數不相同
  • Jvm函式簽名的概念:函式名、引數列表
  • 跟返回值沒有關係
預設引數
  • 為函式引數設定一個預設值
  • 可以為任意位置的引數設定預設值
  • 函式呼叫產生混淆時用具名引數
方法過載與預設引數
  • 方法過載與預設引數可以互相轉換,在Java中呼叫有預設引數的方法時,該方法需要使用註解@JvmOverloads
  • 避免定義關係不大的過載方法

八、擴充套件成員(二次加工)

  • 為現有類新增方法、屬性
fun X.y():Z{...}
val X.m 
//注意擴充套件屬性不能初始化,類似介面屬性
  • Java 呼叫擴充套件成員類似呼叫靜態方法

九、屬性代理

  • 定義方法
val/var <property name>: <Type> by <expression>
  • 代理者需要實現相應的setValue/getValue方法
  • by lazy 就是在第一次使用的時候才去例項化物件

十、資料類(data class)

  • 預設實現 copy()、toString()、equals()等方法
  • 編譯器預設生成component[1-N]方法,可以自己複寫
data class China(val code:Int,name: String)
val (a,b) = China(0,"中國")
pringln("$a -> $b")
  • allOpen和noArg 外掛解決data class 的類被解析成final類,並且無空構造方法的問題
//build.gradle 中的 dependencies 中新增 
dependencies{
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlin_version"
    classpath "org.jetbrains.kotlin:kotlin-allopen:$kotlin_version"
}

//build.gradle 中 新增外掛的應用
apply plugin: 'kotlin-noarg'
apply plugin: 'kotlin-allopen'

// 外掛的配置

noArg{
    annotation("註解類名")
}

allOpen{
    annotation("註解類名")
}
  • 屬性需要寫到構造方法,初始化時需要傳入引數

十一、內部類

匿名內部類
  • 沒有定義名字的類
  • 類名編譯時生成,類似Outter$1.class
  • 可繼承父類、實現多個介面,與Java 不一樣

十二、列舉類

  • 例項可數的類,注意列舉也是類
  • 可以修改構造方法,新增成員
  • 可以提升程式碼的表現力,也有一定的效能開銷

十二、密封類(sealed class)

  • 子類可數的類
  • <V1.1,子類必須定義為密封類的內部類
  • v1.1開始,子類只需要與密封類在同一個檔案中
  • 子類可以有多個構造引數
  • 表示狀態適合使用列舉,需要傳輸指令時適合使用密封類

上一篇:(一)Kotlin 面向物件

下一篇:(三)Kotlin 高階函式