8.Kotlin 扩展
-
扩展函数
我们可以在任何时刻,任何地方,去帮类添加扩展函数,形式就是如下
fun 扩展类.扩展方法(){ println("123456") }
然后能在任何地方任何时刻都能使用这个扩展的方法。
如果扩展函数和成员函数同名,那么优先使用成员函数。
可以扩展一个空的对象,空的对象我们使用
Any?
去表示fun Any?.newString(): String { if (this == null) return "null" // 空检测之后,“this”会自动转换为非空类型,所以下面的 toString() // 解析为 Any 类的成员函数 return toString() }
这样一来我们在任何时刻去调用
toString()
方法的话都不会出现空指针的异常 -
扩展属性
我们还能针对属性做扩展,比如我们想要为
List
类加一个属性lastIndex
,代表列中的最后一个值的索引。val <T> List<T>.lastIndex : Int get() = size - 1
扩展属性只能用
val
来形容,即扩展的属性只能读取,不能修改。 -
伴生对象的扩展
伴生对象是我们在kotlin中一般用来处理单例的方式,可以简要的在此做一下说明,我们主要使用
companion
关键字来处理//kt文件 class TestInstance{ companion object } //decompile java public final class TestInstance { public static final TestInstance.Companion Companion = new TestInstance.Companion((DefaultConstructorMarker)null); public static final class Companion { private Companion() { } public Companion(DefaultConstructorMarker $constructor_marker) { this(); } } }
就是比较经典的单例模式,在kotlin中我们可以直接通过
TestInstance.Companion
的方式去访问这个类的单例,我们可以理解成就是TestInstance.getInstance()
方法半生对象的扩展如下:
fun TestInstance.Companion.newFun(a : String) : Int{ val b = a + "1" return b.length } val TestInstance.Companion.property : Int get() = 1
-
扩展的作用域
作用域较广,跨包名调用也可以直接通过
import
的方式直接使用。 -
扩展中遇到的各种冲突或同名问题
-
情况1 同名扩展函数
如果出现了同名扩展函数,则调用内部函数,不调用扩展函数
fun D.toString(){ Log.e("extension", "toString") }
并没有用,最终会调用类
D
自己的toString
方法 -
情况2 扩展函数中调用内部同名函数
扩展函数中出现了扩展类中和本类中都有的函数,以扩展类中的为主,若想使用本类中的函数,需要加上标注
this@ClassName
class D { fun hello(){} } class C { fun hello(){} fun D.newFun(){ hello() this@C.hello() } }
第一个
hello
方法用的是D
中的hello
,如果想使用C
中的hello
的话需要加上this@C
-
情况3 继承中出现的扩展
首先,我们应该很容易理解,如下这种情况,即参数类型是
D
,所以用的应该是D的扩展函数foo()
open class D { } class D1 : D() { } open class C { open fun D.foo() { println("D.foo in C") } open fun D1.foo() { println("D1.foo in C") } fun caller(d: D) { d.foo() // 调用扩展函数 } }
如果
C1
继承了C
,同时复写了扩展函数,如下:class C1 : C() { override fun D.foo() { println("D.foo in C1") } override fun D1.foo() { println("D1.foo in C1") } }
那么调用
C1
的caller
方法,无论传D
类型还是D1
类型,最终打印的都是println("D.foo in C1")
-
网友评论