我的Kotlin学习之旅(六)

来源:互联网 发布:数据库黑匣子 编辑:程序博客网 时间:2024/05/19 13:57

扩展
初次见到扩展的概念的时候,确实是有点不太理解的,完全搞不懂这是个什么东东。
翻译文档上是这么说的:
与 C# 和 Gosu 类似, Kotlin 也提供了一种,可以在不继承父类,也不使用类似装饰器这样的设计模式的情况下对指定类进行扩展。我们可以通过一种叫做扩展的特殊声明来实现他。Kotlin 支持函数扩展和属性扩展。
好吧,没怎么看懂,就只能通过具体的例子来理解它了。

这里试一下函数扩展,为了声明一个函数扩展,我们需要在函数名前面添加一个接受者类型来作为前缀(意思是这种类型的对象可以调用该扩展函数),接下来是具体的例子:

 fun ArrayList<Int>.swap(x: Int,y :Int){        val temp = this[y]        this[y] = this[x]        this[x] = temp    }

我在这里定义了一个swap函数,作用是交换类型是ArrayList的对象的指定的两个位置的值,同时这个ArrayList对象的值得类型是Int(这里只是为了举例子方法,其实也可以定义成泛型T)。

然后看一下该函数的使用:

class MainActivity : AppCompatActivity() {        private var mShow: TextView? = null        override fun onCreate(savedInstanceState: Bundle?) {            super.onCreate(savedInstanceState)            setContentView(R.layout.activity_main)            mShow = findViewById(R.id.show) as TextView?            val list: ArrayList<Int> = ArrayList()            list.add(111)            list.add(222)            list.add(333)            list.swap(0,1)            var str = ""            for (i in 0 until list.size) {                str += (""+list[i] + ";")            }            mShow!!.text = str        }    }

我在这里声明了一个类型为ArrayList的list,它的长度是3,0,1,2三个位置上的值分别是 111,222,333
调用list.swap(0,1)交换了0和1位置上的数值,应该是变成 222,111,333
通过xml中的TextView,将数据展示出来,最后显示的结果就是222,111,333
说明这样做是可行的。

至此,总结一下函数扩展:定义了类似于上述的扩展函数之后,函数的类型接受者就可以直接通过实例来调用该函数了。

最后再看一下文档,深入了解一下扩展的概念:
扩展实际上并没有修改它所扩展的类。定义一个扩展,你并没有在类中插入一个新的成员,只是让这个类的实例对象能够通过.调用新的函数。

再来看一个很重要的概念:扩展是被静态解析的

open class C class D: C()fun C.foo() = "c" fun D.foo() = "d"fun printFoo(c: C) {     println(c.foo())} printFoo(D())

用文档里的代码来解释吧,这里有一个可被继承的类C,D继承自C,然后类C有一个扩展函数foo(),它打印的值是“c”,而它的继承者D,也有一个相同名字的扩展函数,打印的值是”d”。最后有一个printFoo(c: C),重点在这里,
它这里接收一个形参,C。由于D继承自C,所以也可以被接收。

那么最后调用printFoo函数,输入D对象,输出的到底是”c”还是”d”呢?
这就用到了这句话:扩展是被静态解析的。这里的扩展函数的调用的决定这在于printFoo函数的那个形参的类型,也就是这里的决定者是C,而不是实际传入的参数。所以只要记住这句话:扩展函数的调用决定于是声明的类型,而不是实际传入的类型

再来看一个优先级问题:如果一个类中,有一个和该类的扩展函数同名同参数的成员函数,那么当该类的对象在调用该名称的方法时,会调用哪个呢?
答案:如果有同名同参数的成员函数和扩展函数,调用的时候必然会使用成员函数
也就是说,成员函数的优先级要比扩展函数的优先级要高

可空的接收者
扩展可以使用空接收者类型进行定义。这样的扩展使得,即使是一个空对象仍然可以调用该扩展,然后在扩展的内部进行 this == null 的判断。这样你就可以在 Kotlin 中任意调用 toString() 方法而不进行空指针检查:空指针检查延后到扩展函数中完成

fun Any?.toStrings(): String {    if (this == null) return "null"    // 在空检查之后,`this` 被自动转为非空类型,因此 toString() 可以被解析到任何类的成员函数中    return toString()}

属性扩展

直接看例子:

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

使得类型是ArrayList的对象的名为lastIndex的扩展属性的值为 list的长度 - 1,即返回的是list的最后一个值得下标
亲测有用哟
需要注意的点:
扩展并不会真正给类添加了成员属性
扩展属性只能够通过明确提供 getter 和 setter方法来进行定义.

阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 宝贝排名靠后怎么办 平板电脑坏了怎么办 淘宝号不能登陆怎么办 淘宝登陆不上怎么办 手机登不了淘宝怎么办 淘宝被限制登陆怎么办 手机淘宝无响应怎么办 开超市进货渠道怎么办 网上买家电售后怎么办 深圳购物卡过期怎么办 美图手机卡死了怎么办 淘宝做代理发货怎么办 被灵猫电商骗了怎么办 淘宝店铺没访客怎么办 开淘宝没有货源怎么办 苹果5商城打不开怎么办 品质退款率高怎么办 淘宝迟迟不发货怎么办 华为屏幕黑了怎么办 小米手机丢了怎么办 手机拨号后黑屏怎么办 手机拨号就黑屏怎么办 魅族mx4发热严重怎么办 flyme密码忘了怎么办 魅族mx5信号不好怎么办 魅族mx5信号差怎么办 魅族mx5内存不够怎么办 华为mate8音质差怎么办 华为mate8信号弱怎么办 蓝牙耳机开不了怎么办 qq充话费没到账怎么办 淘宝充q币没到账怎么办 uc账号忘记了怎么办 顺丰不让验货怎么办 q币充错账号了怎么办 通惠购遭遇骗了怎么办 百合网打电话来怎么办 天猫超市假货怎么办 iphone6摔弯了怎么办 京东商城怎么办分期 荣耀4x内存不足怎么办