Kotlin之擴展

  • 2019 年 10 月 7 日
  • 筆記

目前大多說的高級語言在對已有的class進行擴展大多採用繼承或者裝飾器的方式,但是這些方式大都會破壞原類,對整個項目來說是一種侵入式極強的方式……Kotlin在function這方面吸取了一些動態語言(OC)仿照姊妹篇swift的方式可以對已有的class進行方法擴展達到了可以在不重新已有類修改程式碼或者使用子類的方式對類進行功能的擴展……

聲明一個擴展方法

對於一個方法可定是有接收者,因此在方法擴展需要添加class的聲明啦,我們看如下程式碼:

class Animal{}  fun Animal.move() {    }

我們首先聲明了一個class叫做Animal,然後擴展一個move的能力,那麼怎麼使用這個能力呢?

val animal = Animal()   animal.move()

可以看出它與成員方法並沒有什麼不同之處。其實本質還是有區別的,我們對上栗進行修改,class內部添加一個move方法

class Animal {      fun move() {        }  }    fun Animal.move() {    }

這時候假如調用move的時候如何呢,使用的是擴展方法還是成員方法呢?

如果一個類定義有一個成員函數與一個擴展函數,而這兩個函數又有相同的接收者類型、 相同的名字,並且都適用給定的參數,這種情況總是取成員函數

擴展為靜態解析

擴展不是原有類進行修改來實現擴展的,它僅僅是可以通過類的實例化之後通過點語法調用的一個函數而非是類實例的一個成員方法。更確切的說它是根據程式碼聲明處的那個類型來決定怎麼調用分發的而不是由動態運行時所屬的類型決定怎麼分發的

上面的描述整體有點繞,但是整體就是說調用時有程式走到哪裡爵溪成程式碼程式碼聲明的是什麼類型就通過這個類型去搜尋對應的類對應的方法擴展

我們修改程式碼如下:

open class Animal {    }  //子類  class Dog: Animal() {    }  //子類    class Duck : Animal() {    }  //擴展  fun Dog.move() {    }  //擴展  fun Duck.move() {    }  fun Animal.move() {    }    //調用      var animal: Animal = Dog()      animal.move()

當我們調用move時會調用哪個的move擴展呢?下面我們復盤一下

1 聲明變數為Animal類型

2 動態實例化Dog實例

3 變數調用move

根據擴展的靜態解析規則來說調用時回溯到變數聲明之處為Animal因此調用Animal申明的擴展方法move

擴展屬性

擴展屬性與擴展方法類似

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

擴展作用域

杜宇擴展要想挎包訪問,需要在包內import擴展出的方法