Kotlin Tutorial(15)介面與實作(上) by Michael | CodeData
top

Kotlin Tutorial(15)介面與實作(上)

分享:

Kotlin Tutorial(14)列舉型態 << 前情

設計功能比較複雜的應用程式,除了基本的繼承架構外,通常會使用介面(interface)提供更靈活的設計架構。各種平台與框架也會使用介面提供特定的功能,例如Android平台與JavaFX的元件監聽架構(listener),用來執行使用者操作功能的設計。這一章先說明Kotlin介面的宣告、實作與使用。

宣告與實作Kotlin介面

Kotlin使用interface關鍵字宣告介面,可以宣告與類別一樣的屬性與函式,不過介面通常用來宣告沒有初始化的變數,稱為抽象屬性變數(abstract properties),還有沒有實作的函式,稱為抽象函式(abstract function)。下面是宣告Kotlin介面的語法:

interface 介面名稱 [: 介面名稱,...]{
    // 一般屬性變數
    val | var 變數名稱 [: 型態] = 值
    // 抽象屬性變數
    val | var 變數名稱 : 型態 

    // 一般函式
    fun 函式名稱(參數名稱 : 參數型態,...) : 回傳型態 { ... }
    // 抽象函式
    fun 函式名稱(參數名稱 : 參數型態,...) : 回傳型態 
}

介面通常用來整合不同的繼承架構,同樣可以使用多型的特性,讓應用程式的設計更加靈活。下面是一個Kotlin介面的範例:

package net.macdidi5.kotlin.tutorial.ch15

// 使用interface宣告介面
interface Greeting01 {
    // 宣告沒有實作的抽象函式
    fun greet(name: String): String
}       

一個宣告好的介面可以讓類別實作,下面是類別實作介面的語法:

class 類別名稱 : 介面名稱,... {
    // 覆寫(override)介面的抽象屬性變數與抽象函式
    // 其它類別需要的宣告
}

類別在實作介面以後,必須實作介面宣告的抽象函式,否則會發生編譯錯誤。下面是實作與使用介面的範例:

package net.macdidi5.kotlin.tutorial.ch15

...

// 宣告實作Greeting01介面的類別
class Greeting01Impl : Greeting01 {
    // 使用override關鍵字
    // 覆寫Greeting01介面的greet抽象函式
    // 函式的宣告必須和介面的抽象函式一樣
    override fun greet(name : String): String {
        return "Hello! $name!"
    }
}

// 宣告一個接收Greeting01物件參數的函式
fun sayHello(greeting : Greeting01) {
    println(greeting.greet("Simon"))
}

fun main(args: Array<String>) {

    // 建立實作Greeting01介面的物件
    val greeting01 = Greeting01Impl()

    // 呼叫函式並傳送Greeting01物件
    sayHello(greeting01)
    // 顯示: Hello! Simon!
}    

包含抽象屬性的介面

Kotlin介面跟類別一樣,可以宣告一般的的屬性變數與函式。除了一般常見的抽象函式外,也可以宣告抽象屬性,讓實作的類別決定屬性的值。下面是一個包含抽象屬性與其它宣告的介面:

package net.macdidi5.kotlin.tutorial.ch15

interface Greeting02 {
    // 宣告抽象屬性變數
    val name : String

    // 宣告一般屬性變數
    val upperName : String
        get() = name.toUpperCase()

    // 宣告抽象函式
    fun message(): String

    // 宣告一般函式
    fun displayName() {
        println("Name: $name")
    }

    // 宣告一般函式
    fun displayGreeting() {
        println("Hello, $upperName")
    }
}

實作包含抽象屬性介面的類別,必須覆寫介面宣告的抽象屬性,其它抽象函式也必須覆寫:

package net.macdidi5.kotlin.tutorial.ch15

// 宣告實作Greeting02介面的類別
class Greeting02Impl : Greeting02 {

    // 覆寫Greeting02介面的name抽象屬性
    override val name = "Simon"

    // 覆寫Greeting02介面的message抽象函式
    override fun message(): String {
        return "Hello! $name!"
    }

}    

// 宣告一個接收Greeting02物件參數的函式
fun sayHello02(greeting02 : Greeting02) {
    println(greeting02.message())
}

fun main(args: Array<String>) {

    // 建立實作Greeting02介面的物件
    val greeting0201 = Greeting02Impl()

    // 使用Greeting02介面宣告的屬性變數
    println("${greeting0201.name}, ${greeting0201.upperName}")
    // 顯示: Simon, SIMON

    // 呼叫Greeting02介面宣告的一般函式
    greeting0201.displayName()
    // 顯示: Name: Simon
    greeting0201.displayGreeting()
    // 顯示: Hello, SIMON

    // 呼叫函式並傳送Greeting02物件
    sayHello02(greeting0201)
    // 顯示: Hello! Simon!

}

介面的繼承

與類別的繼承一樣,介面也可以繼承介面,不過類別只能繼承一個父類別,通常會稱為「單一繼承」,而介面可以繼承多個介面。下面是之前說明過的介面宣告:

package net.macdidi5.kotlin.tutorial.ch15

// 使用interface宣告介面
interface Greeting01 {
    // 宣告沒有實作的抽象函式
    fun greet(name: String): String
}

為了靈活的設計應用程式架構,你可以讓介面繼承另外一個介面,繼承的效果與類別繼承是類似的,同樣會繼承父介面宣告的抽象與非抽象屬性與函式,

package net.macdidi5.kotlin.tutorial.ch15

// 使用interface宣告介面,指定Greeting01為父介面(super interface)
interface Greeting03 : Greeting01 {
    // 宣告沒有實作的抽象函式
    fun getGreeting() : String
}

實作上面的介面時,就必須實作所有的抽象屬性與函式:

package net.macdidi5.kotlin.tutorial.ch15

// 宣告實作Greeting02介面的類別
class Greeting03Impl : Greeting03 {

    // 覆寫Greeting01介面的greet抽象函式
    override fun greet(name : String): String {
        return "Hello! $name!"
    }

    // 覆寫Greeting03介面的getGreeting抽象函式
    override fun getGreeting(): String {
        return greet("Mary")
    }

}

fun main(args: Array<String>) {

    // 建立實作Greeting03介面的物件
    val greeting0301 = Greeting03Impl()

    println(greeting0301.greet("Simon"))
    println(greeting0301.getGreeting())
    // 顯示:
    //    Hello! Simon!
    //    Hello! Mary!

}

使用匿名類別實作介面

上面說明的方式,先宣告一個實作介面的類別,再建立與使用這個類別的物件。不過如果應用程式須要實作介面的類別,只會在特定的地方使用,建議可以使用匿名類別(anynomous clas)的作法,可以讓程式碼更簡單一些。下面是使用匿名類別宣告與實作介面的語法:

val 變數名稱 = object : 介面名稱,... {
    // 覆寫(override)介面的抽象屬性變數與抽象函式
    // 其它類別需要的宣告        
}

以上面說明的應用來說,使用object關鍵字,可以一次完成宣告類別與建立物件的工作:

package net.macdidi5.kotlin.tutorial.ch15

import java.time.LocalDate
import java.time.LocalDateTime

...

// 宣告一個接收Greeting01物件參數的函式
fun sayHello(greeting : Greeting01) {
    println(greeting.greet("Simon"))
}

fun main(args: Array<String>) {

    ...

    // 宣告與實作Greeting01介面的物件
    val greeting02 = object : Greeting01 {
        override fun greet(name : String): String {
            return "Hello! $name! ${LocalDate.now()}"
        }
    }

    sayHello(greeting02)
    // 顯示: Hello! Simon! 2017-12-19

    // 在方法的參數宣告與實作Greeting01介面的物件
    sayHello(object : Greeting01 {
        override fun greet(name : String): String {
            return "Hello! $name! ${LocalDateTime.now()}"
        }
    })
    // 顯示: Hello! Simon! 2017-12-19T11:51:40.792

}

下面是另外一個使用匿名類別實作介面的範例:

package net.macdidi5.kotlin.tutorial.ch15

import java.time.LocalDate
import java.time.LocalDateTime

...

// 宣告一個接收Greeting02物件參數的函式
fun sayHello02(greeting02 : Greeting02) {
    println(greeting02.message())
}

fun main(args: Array<String>) {

    ...

    // 宣告與實作Greeting02介面的物件
    val greeting0202 = object : Greeting02 {
        override val name = "Mary"

        override fun message(): String {
            return "Hello! $name! ${LocalDate.now()}"
        }
    }

    sayHello02(greeting0202)
    // 顯示: Hello! Mary! 2017-12-19

    // 在方法的參數宣告與實作Greeting02介面的物件
    sayHello02(object : Greeting02 {
        override val name = "Mary"

        override fun message(): String {
            return "Hello! $name! ${LocalDateTime.now()}"
        }
    })
    // 顯示: Hello! Mary! 2017-12-19T11:57:01.340

}    

下一步

瞭解Kotlin介面的基本概念以後,在開發Android或Java應用程式的時候,也會經常使用Java介面,接下來準備認識如何使用kotlin程式語言實作Java介面。

相關的檔案都可以在GitHub瀏覽與下載。

http://github.com/macdidi5/Kotlin-Tutorial

後續 >> Kotlin Tutorial(16)介面與實作(下)

分享:
按讚!加入 CodeData Facebook 粉絲群

相關文章

留言

留言請先。還沒帳號註冊也可以使用FacebookGoogle+登錄留言

熱門論壇文章

熱門技術文章