安卓語言基礎之Kotlin的面向對象編程

語言: CN / TW / HK

theme: smartblue

本文正在參加「金石計劃 . 瓜分6萬現金大獎」

前言

強大而靈活的RecyclerView Adapter——BRVAH(框架引入與BaseQuickAdapter使用篇) - 掘金 (juejin.cn)這篇文章中,我自定義了一個屬性類,但其實當時我寫的時候是恍惚了好一陣,因為習慣用Java語言開發安卓的我,一時不知道用Kotlin如何寫類與其構造方法,異常尷尬,於是立刻翻出教程學習起來,然後才繼續完成了這個Adapter的Demo,下面我們就來看看如何使用Kotlin完成面向對象編程吧!

image.png

正篇

類的寫法

和Java一樣的地方是都要用class關鍵字: ```Kotlin class Person { var name = "" var age = 0

fun profile() {
    println("name : $name, age : $age")
}

} 也是大括號裏面寫成員變量和成員方法,實例化也很簡單:Kotlin val p = Person() ``` 只是沒有new這個關鍵字,這是Kotlin的機制。

繼承

Kotlin的繼承不需要寫extends關鍵字,而且Kotlin的繼承機制也與Java不一樣,在Kotlin中任何一個非抽象類默認都是不可繼承的,原因與val關鍵字類似,因為類和變量一樣,最好不可變,如果一個類允許被繼承,它就無法預知子類會如何實現,從而導致出現一些未知風險,所以當一個類不是用來繼承的,在Java中也應該用final聲明,禁止其繼承。

而Kotlin已經主動幫我們做好了,它默認所有非抽象類都不可被繼承,而抽象類是不能直接實例化,需要子類繼承才能創建實例,所有抽象類就是必須要被繼承才行。

但如果我們想要讓一個類可以被繼承,其實只需要加上關鍵字open即可: ```Kotlin open class Person { var name = "" var age = 0

fun profile() {
    println("name : $name, age : $age")
}

} 然後在Kotlin中Java的繼承關鍵字extends變成了“:”(冒號):Kotlin class Teacher : Person() { var num = 0 var className = "" } ``` 我們看到父類還加上了括號,這就是和下面要説的構造函數有關

構造函數

```Kotlin open class Person( val name : String, val age : Int ) { fun profile() { println("name : $name, age : $age") } }

class Teacher(var num : Int, var className : String, name: String, age: Int ) : Person(name, age) {

} ``` 我們可以看到和Java的構造函數不同,它不是寫在類方法體的,而是像方法聲明參數一樣寫在類名後的小括號內,所以父類繼承時也就需要小括號,同時我們將子類Teacher後的這個小括號內容稱作主構造函數,任何一個類只能有一個主構造函數,當然,有主構造函數,也會有次構造函數,這裏先不過多闡述,後面有時間再更新到本文中。

有構造函數的類實例化: Kotlin val teacher = Teacher(25, "A", "SchoolPerson", 30)

接口

Kotlin的接口和Java的接口聲明類似: Kotlin interface Teach { fun teach() fun work() } 繼承後需要去實現接口的所有方法,繼承不需要用Java的implements關鍵字,還是使用冒號,多個類時中間用逗號分開,接口不用名稱後加小括號,因為它沒有構造函數可調: ```Kotlin class Teacher(var num : Int, var className : String, name: String, age: Int ) : Person(name, age), Teach { override fun teach() { TODO("Not yet implemented") }

override fun work() {
    TODO("Not yet implemented")
}

} ``` 其中,override為Kotlin重寫方法的關鍵字,和Java的@Override註解類似

此外,Kotlin也支持接口函數默認實現,即可以在接口中對函數實現,然後在實現接口時就不用強制實現該函數,自由選擇是否實現該函數,不實習就調用默認實現方法: Kotlin interface Teach { fun teach() //默認實現 fun work() { println("Work!!") } } 繼承後可以選擇對已經默認的work方法實現或不實現:

image.png

默認實現去除繼承中的實現方法不報錯:

image.png

未實現繼承後也不實現的話會報錯:

image.png

這種使用接口的編程方式也叫面向接口編程,亦稱多態。

數據類

數據類通常用於將服務器端或數據庫的數據映射到內存中,為編程邏輯提供數據模型的支持,我們常説的MVC,MVP,MVVM這些架構模式的M即指代數據類

前言中那個圖片其實就是想寫數據類但當時還不知道Kotlin如何寫就導致出現了個四不像的,但也勉強符合預期,後面會進行更正,那麼數據類該如何寫呢,我之所以寫錯就是因為Java中數據類實在不一樣,在Java中我們通常要重寫equals()、hashCode()和toString()方法,讓這個類擁有數據類的功能: ```Java public class ModelDemo { String name; int age;

public ModelDemo(String name, int age) {
    this.name = name;
    this.age = age;
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof ModelDemo)) return false;
    ModelDemo modelDemo = (ModelDemo) o;
    return age == modelDemo.age && Objects.equals(name, modelDemo.name);
}

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

@Override
public String toString() {
    return "ModelDemo{" +
            "name='" + name + ''' +
            ", age=" + age +
            '}';
}

} 而在Kotlin中,只要你加上關鍵字data就能自動幫你處理好這些,不需要做這些無用的工作:Kotlin data class ModelDemo(val name: String, val age: Int) 就這一句,簡簡單單。然後一樣可以實現上面Java代碼重寫的方法的作用:Kotlin val modelDemo = ModelDemo("Name", 18) val modelDemo1 = ModelDemo("Name", 18) println(modelDemo) println(modelDemo == modelDemo1) ```

image.png

單例類

首先我們瞭解一下單例模式:

單例模式,最常用、最基礎的設計模式之一,可用於避免創建重複對象,在全局最多隻能擁有一個實例。

單例模式的寫法很多,我們這邊先看一下Java的一種常見寫法: ```Java public class SingleDemo {

private static SingleDemo instance;

public SingleDemo() {}

public synchronized static SingleDemo getInstance() {
    if (instance == null) {
        instance = new SingleDemo();
    }
    return instance;
}

public void singleDemoTest() { System.out.println("singleDemoTest is called"); } } 調用:Java SingleDemo singleDemo = SingleDemo.getInstance(); singleDemo.singleDemoTest(); Java中看起來實現單例也不難,但當我看到Kotlin中時,真的笑了:Kotlin object SingleDemo { } 對,這就是Koltin版的單例,如果再加上Java中實現的方法:Kotlin object SingleDemo { fun singleDemoTest() { println("singleDemoTest is called") } } 調用看起來像在使用Java靜態方法的調用,其實是Kotlin已經幫我們自動創建好了SingleDemo的實例,且會保證全局只存在一個SingleDemo實例:Koltin SingleDemo.singleDemoTest() ``` 只能説不愧是晚出來的語言,優勢真明顯,只需要把class關鍵字換成object,一個單例簡簡單單完成創建。

總結

本文將Kotlin的面向對象編程介紹了一遍,真的感受到了Kotlin的方便與優勢,感謝大家的閲讀!