漫画:Kotlin 的扩展细节探究

作者:CQITer小编 时间:2018-05-19 09:21

字号
人工智能+区块链的发展趋势及应用调研报告

 

漫画:Kotlin 的扩展细节探究

扩展

漫画:Kotlin 的扩展细节探究

扩展并不是 Kotlin 首创的,在 C# 和 Gosu 里,其实早就有类似的实现,Kotlin 本身在设计之初,就参考了很多语言的优点!

Kotlin 可以利用扩展,在不继承父类也不使用任何装饰器设计模式的情况下,对指定的类进行功能的扩展。

Kotlin 的扩展包含了扩展函数和扩展属性,需要适用特殊的声明方式来完成。也就是说你可以对任何类,增加一些方法或者属性,来增强它的功能。

比较常见的场景,就是原本我们需要实现的各种 SpUtils、ViewUtils 之类的各种 XxxUtils 工具类。如果需要,我们可以直接在对应的类上,进行直接扩展。

说的这么厉害,举个实际的例子就可以说明一切了。我一般会在项目内建立一个 SpUtils 的帮助类,来帮我们快速的操作 SharePreferences。

fun Context.getSpString(key:String):String{ 

    val sp = getSharedPreferences("cxmy_sp",Context.MODE_PRIVATE) 

    return sp.getString(key,""

在这个例子中,我们对 Context 类进行扩展,为了让它能够支持快速的从 SharePreferences 中获取到持久化的数据。当然,我们还是要传递进去一个我们存储数据的 Key。

这样使用它就非常的简单了,我们可以直接能够持有 Context 的地方,直接调用 getSpString() 方法。

// Activity 中 

getSpString("cxmy"

// or 

mContext.getSpString("cxmy"

漫画:Kotlin 的扩展细节探究

扩展是静态解析的

我们知道,Kotlin 最终依然会被编译成 Java 的字节码在虚拟机中运行。Kotlin 也无法突破 Java 中不被允许的操作限制,所以它并不能真正的修改他们所扩展的类。

通过定义一个扩展,其实你并没有在一个现有类中,真的插入一个新的方法或者属性,仅仅是可以通过该类型的变量,用点表达式调用这个新方法或者属性。

类是允许继承的,而静态解析这一规则,就是为了在类的继承这一点上,不存在二义性。

当父类以及它的子类,都通过扩展的方式,增加一个 foo() 方法的时候,具体在调用的时候,是调用父类的 foo() 方法还是子类的 foo() 方法,完全取决于调用时,表达式所在的类型决定的,而不是由表达式运行时的类型决定的。

这里强调的扩展是静态解析的,即他们不是根据接受者类型的虚方法来判定调用那个方法。

一例胜千文,我们依然来举个例子。

open class A() 

class B:A(){ 

fun A.foo(){ 

    Log.i("cxmy","A.foo"

fun B.foo(){ 

    Log.i("cxmy","B.foo"

fun printFoo(a: A){ 

    a.foo() 

printFoo(B()) 

在这个例子中,我们传递进去的是 B 对象,但是实际上会调用 A.foo() 方法,所以输出应该是 "A.foo()"。

这也印证了扩展是依据调用所在的表达式类型来决定的,而不是由表达式运行时的类型决定的。

在 Kotlin 中,使用 is 操作符,会让代码块中的类型有一次隐式转换,但是它对扩展是无效的,如果有特殊要求,可以使用 as 操作符显式的进行强转,方可生效。

fun foo(){ 

    val b = B() 

    b.foo() 

    if(b is A){ 

      (b as A).foo() 

      b.foo() 

    } 

随手运行一下,它的结果就明朗了。

B.foo() 

A.foo() 

B.foo() 

责任编辑:CQITer新闻报料:400-888-8888   本站原创,未经授权不得转载
关键词 >>Kotlin 扩展 XxxUtils
继续阅读
热新闻
推荐
关于我们联系我们免责声明隐私政策 友情链接