iT邦幫忙

2022 iThome 鐵人賽

DAY 8
0
Mobile Development

【Kotlin Notes And JetPack】Build an App系列 第 8

Day 8.【Classes and Objects】Extensions

  • 分享至 

  • xImage
  •  

今天要來看看我們可以透過 Extensions 做到什麼,在開始前要先了解什麼是 Extensions ,以下如有解釋不清或是描述錯誤的地方還請大家多多指教:

什麼?

在不需要繼承以及使用任何 design pattern 來擴充原有的 class 或是 interface 的前提下,Koltin 提供了一個可以擴充新方法或屬性,且不會改變 class 或 interface 本身的內容物。

| Extension Function

針對一個既有的 class 建立 Extension Function ,那個 class 的 name 會在前綴當作 receiver type,就如下面的範例,假如今天想針對 ImageView 的 class 擴充一個設定灰階的方法:

// 這邊有用到 funciotn type
fun ImageView.setGreyColorScale(condition: () -> Boolean) {
    ColorMatrix().also {
        it.setSaturation(0f) //0 means grayscale
        val colorFilter = ColorMatrixColorFilter(it)
        this.colorFilter = if (condition()) colorFilter else null 
		// 'this' 是接收的 imageView
    }
}

// 實際應用
productImageView.setGreyColorScale { a > 0 }

// or
fun ImageView.setGreyColorScale(isNeedGrey: Boolen) {
    ColorMatrix().also {
        it.setSaturation(0f) //0 means grayscale
        val colorFilter = ColorMatrixColorFilter(it)
        this.colorFilter = if (isNeedGrey) colorFilter else null 
		// 'this' 是接收的 imageView
    }
}

// 實際應用
productImageView.setGreyColorScale(a > 0)

除此之外需要避免和既有的 function 同名,除非是不同 arguments overload 原有的 function:

class Example {
    fun printFunctionType() { println("Class method") }
}

fun Example.printFunctionType(i: Int) { println("Extension function #$i") }

Example().printFunctionType(1)
// get Extension function #1

| 泛型

如果想要一個通用型態的 function,泛型也可以做擴充:

fun <T> MutableList<T>.clearAndAddAll(replace: MutableList<T>) {
    clear()
    addAll(replace)
}

| Extension Properties

因為 extensions 並不是真的 insert 任何參數或方法在 class 中,extension property 並不會有 backing field,所以屬性不能初始化:

val <T> List<T>.lastIndex: Int
    get() = size - 1

// e.g. val <T> List<T>.lastIndex: Int = 1
// error: initializers are not allowed for extension properties

| Companion Object Extensions

companion object 因為沒有命名,所以擴充的名稱為 Companion,呼叫時可只用 class 名稱當 receiver。

class ExampleClass {
    companion object { }  // will be called "Companion"
}

fun ExampleClass.Companion.printName() { println("companion") }

fun main() {
    ExampleClass.printName()
}

如何?

通常我會把較常做的事情或是通用的事情變成 Extension Function,像是需要動態更改元件的 margin 或 padding 時,我們需要做 type 的轉換。

fun Float.toPx() = this * Resources.getSystem().displayMetrics.density
fun Float.toDp() = this / Resources.getSystem().displayMetrics.density

大部分會將 function 定義在最高層級,直接寫在檔案的 package name 下,在這邊我會建立一個空的檔案就取名 CommonExtensions:
https://ithelp.ithome.com.tw/upload/images/20220921/20151145tmTwKymFk4.png

Reference

Official Kotlin
Kotlin.tips


上一篇
Day 7.【Classes and Objects】Enum Classes
下一篇
Day 9.【Classes and Objects】Delegate Properties
系列文
【Kotlin Notes And JetPack】Build an App30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言