扩大函数

Kotlin扩大函数可能对⼀个类扩大新性能⽽⽆需继承该类或者使⽤像装璜者这样的设计模式。利用他能够缩小很多代码,晋升咱们的开发效率。

扩大函数的申明

申明⼀个函数,而后让被扩大的类型作为函数的前缀就能够了,比方上面对TextView的扩大

fun TextView.setDrawableLeft(drawableId: Int?) {    val drawable = ContextCompat.getDrawable(this.context, drawableId)    if (drawable == null) {        setCompoundDrawables(            null,            compoundDrawables[1],            compoundDrawables[2],            compoundDrawables[3]        )    } else {        drawable.apply {            setBounds(0, 0, minimumWidth, minimumHeight)            setCompoundDrawables(                drawable,                compoundDrawables[1],                compoundDrawables[2],                compoundDrawables[3]            )        }    }}

而后咱们就能够应用TextView的实例调用setDrawableLeft()办法。尽管看上去如同咱们为TextView新增了一个办法,然而其实扩大是动态的,他并没有为扩大类型中插入新的办法

那么他是如何实现的呢,咱们反编译以下class文件,查看对应的java文件就明确了

扩大函数原理

public static final void setDrawableLeft(@NotNull TextView $this$setDrawableLeft, @Nullable Integer drawableId){    //省略其余代码}

原来是给咱们生成了一个对应的java静态方法,第一个参数就是接受者类型的对象,所以在办法外部能够拜访这个类中的成员。

既然是生成了java代码,那么这个办法就能够被其余java代码拜访

TextViewKt.setDrawableLeft(textview,drawableId)

扩大属性

和扩大函数相似,这种扩大也是动态的,并没有给原来的类增加新的属性

扩大属性的申明

val StringBuilder.lastChar: String    get() {        if (this.isEmpty()) {            return ""        }        return this.substring(length - 1)    }

申明形式和扩大函数也相似,须要一个接受者类型,在作用域类,this就代表这个接受者对象,因为这里lastChar咱们定义的是val,所以只用定义get()办法就能够了,如果是var类型,还须要定义set()办法,扩大字段的应用和失常字段一样。

val s = StringBuilder("value")println(s.lastChar)

扩大属性原理

持续反编译查看对应的java源码

public static final String getLastChar(@NotNull StringBuilder $this$lastChar)  {    Intrinsics.checkNotNullParameter($this$lastChar, "<this>");    if ((((CharSequence)$this$lastChar).length() == 0 ? 1 : 0) != 0) {      return "";    }    String str = $this$lastChar.substring($this$lastChar.length() - 1);Intrinsics.checkNotNullExpressionValue(str, "this.substring(length - 1)");return str;  }

能够看到其实也是生成了一个静态方法,java代码调用如下

StringBuilder s = new StringBuilder("value");String lastChar = EXTKt.getLastChar(s);