1. 程式人生 > >Kotlin中的面向物件(一)

Kotlin中的面向物件(一)

面向物件

面向物件的含義大家應該並不陌生,通過將事物抽象成物件,大大簡化了程式的開發難度。我們常用的Java、Python、C++都屬於面向物件的程式語言。Kotlin和java很相似,也是一種面向物件的語言。作為Kotlin中最重要的一部分,我們可以通過了解Kotlin的OOP進而瞭解這門語言,本文將從類、屬性、介面、物件等多個方面介紹Kotlin的面向物件的特性。

和大部分語言類似,Kotlin使用class作為類的關鍵字,當我們宣告一個類時,需要通過class加類名的方式實現:
class ClassDemo{
    
}
在宣告一個類的時候,至少需要包含class關鍵字以及後面的類名,同時也可以根據需要增加類頭(用來宣告一些引數)和類體(花括號{}中包含的內容,可省略)。

建構函式

與java不同的是,雖然都可以包含多個建構函式,但java中的各個建構函式都是平級的,而Kotlin中卻分為了兩級(主建構函式和二級建構函式),主建構函式是包含在類頭中的,需要在init方法中實現額外的操作,而二級建構函式可以在函式體中實現所有操作
//主建構函式,constructor和init都可省略
class ClassDemo constructor(type:String){
    init{
        System.out.println(type)
    }
}
在主建構函式中傳入的引數可以在類體中為屬性賦值,也可以直接在主建構函式中宣告
class ClassDemo(type:String, var prop2: String = type){
        var prop1 = type
}
二級建構函式必須包含constructor
class ClassDemo{
        constructor(type:String){
                System.out.println(type)
        }
}
對於有主建構函式的類而言,每個二級建構函式都要,或直接或間接通過另一個二級建構函式代理主建構函式。在同一個類中代理另一個建構函式使用 this 關鍵字:
//包含主建構函式的二級建構函式
class ClassDemo(type:String){
        constructor(type:String, param:String):this(type){
                System.out.println(type + param)
        }
}
無論有沒有宣告主建構函式,Kotlin都會提供一個建構函式的方法,有時可能不希望將某個類的建構函式暴露出來(比如實現單例模式時),那麼就需要對主建構函式進行處理
class ClassDemo private constructor(){

}
當我們想建立例項時,可以直接呼叫對應的建構函式進行建立
var demo = ClassDemo("hello world")
val demo = ClassDemo("hello","world")
我們注意到,在Kotlin中無論是宣告屬性還是建立例項,會有兩種方式,var和val,val類似於java中的final,通過它宣告的內容是無法變化的,而var和val相反,宣告的內容既可以讀取也可以修改。

繼承

在Kotlin中,所有的類會預設繼承Any這個父類,但Any並不完全等同於java中的Object類,因為它只有equals(),hashCode()和toString()這三個方法。當我們想定義一個父類時,需要使用open關鍵字
open class Base{

}
然後在子類中使用冒號“:”進行繼承
class SubClass : Base(){

}
如果父類有建構函式,那麼必須在子類的主建構函式中進行繼承,沒有的話則可以選擇主建構函式或二級建構函式
//父類
open class Base(type:String){

}

//子類
class SubClass(type:String) : Base(type){

}

重寫

Kotlin中的重寫和java中也有所不同,因為Kotlin提倡所有的操作都是明確的,因此需要將希望重寫的方法設為open
open fun funDemo() {}
然後通過override標記實現重寫
override fun funDemo() {
     super.funDemo()
 }
override重寫的函式也是open的,如果希望它不被重寫(前提是這個類可以被繼承),可以在前面增加final標籤
open class SubClass : Base{
    constructor(type:String) : super(type){

    }

    final override fun funDemo() {
        super.funDemo()
    }
}
當一個類同時繼承且實現了多個介面時,如果重寫的方法在父類和介面中都有定義,那麼可以通過super<>的方式進行繼承
//介面
interface InterfaceDemo{
    fun funDemo(){}
}

//繼承Base並且實現InterfaceDemo
class SubClass : Base(),InterfaceDemo{
    final override fun funDemo() {
        super<Base>.funDemo()
        super<InterfaceDemo>.funDemo()
    }
}

密封類

密封類用於代表嚴格的類結構,值只能是有限集合中的某中型別,不可以是任何其它型別。這就相當於一個列舉類的擴充套件:列舉值集合的型別是嚴格限制的,但每個列舉常量只有一個例項,而密封類的子類可以有包含不同狀態的多個例項。宣告密封類需要在 class 前加一個 sealed 修飾符。密封類可以有子類但必須全部巢狀在密封類宣告內部。
//密封類
sealed class Expr {
    class Const(val number: Double) : Expr()
    class Sum(val e1: Expr, val e2: Expr) : Expr()
    object NotANumber : Expr()
}

和Kotlin中的類相關的用法就介紹到這裡,文中的完整程式碼見github,在Kotlin中的面向物件(二)中將會介紹屬性、介面等面向物件過程中同樣常見的內容。