3.3 给别人的类添加方法:扩展函数和属性

版权声明:本文为博主原创文章,转载请标注 https://blog.csdn.net/cai784921129/article/details/81318867

理论上讲,扩展函数非常简单,它就是一个类的成员函数,不过定义在类的外面。为了方便阐释,让我们添加一个方法,来计算一个字符串的最后一个字符:

// 扩展函数,它就是一个类的成员函数,不过是定义在类的外面

package strings

fun String.lastChar(): Char = this.get(this.length - 1)

这个类的名称被称为接收者类型;用来调用这个扩展函数的那个对象,叫接收者对象

可以像调用类的普通成员函数一样去调用这个函数

》》》

println("Kotlin".lastChar())

在这个例子中,String就是接收者类型,“Kotlin”就是接收者对象。

从某种意义上说,你已经为String类添加了自己的方法

在这个扩展函数中,可以像其他成员函数一样用this。而且也可以像普通的成员函数一样,省略它。

fun String.lastChar(): Char = this.get(length - 1)

在扩展函数中,可以直接访问到被扩展的类的其他方法和属性,就好像是在这个类自己的方法中访问它们一样,注意,扩展函数并不允许你打破它的封装性。和在类内部定义的方法不同的是,扩展函数不能访问私有的或者是受保护的成员

3.3.1 导入和扩展函数

对于你定义的一个扩展函数,它不会自动地在整个项目生效,如果要使用它你需要导入。Kotlin允许用和导入类一样的语法来导入单个的函数:

import strings.lastChar

val c = "Kotlin“.lastChar()

当然用 * 来导入也是可以的

import strings.*

val c = "Kotlin“.lastChar()

可以使用关键字“as”来修改导入的类火灾函数的名称:

import strings.lastChar as last

>>>

println("Kotlin".last())

在不同的包下有重名的函数时,在导入时给它重新命名就显得很有必要

3.3.2 从Java中调用扩展函数

实质上扩展函数就是静态函数,它把调用对象作为了它的第一个参数。调用扩展函数,不会创建适配的对象或者任何运行时的额外损耗。

这使得从Java中调用Kotlin的扩展函数变得非常简单:调用这个静态函数,然后把接收者对象作为第一个参数传进去即可。和其他顶层函数一样,包括这个函数的Java类的名称,是由这个函数声明的文件名称决定的。假设它声明在一个叫作StringUtil.kt文件中:

char c = StringUtilKt.lastChar("Java")

这个扩展函数被声明为顶层函数,所以,它将会被编译为一个静态函数。

 

3.3.3 作为扩展函数的工具函数

package strings



fun <T> Collection<T>.joinToString2( separator: String = ";", prefix: String = "[", postfix: String = "]"): String {

val result = StringBuilder(prefix)

for ((index, element) in this.withIndex()) {

if (index > 0) result.append(separator)

result.append(element)

}

result.append(postfix)

return result.toString()

}

使用的时候

import strings.joinToString2

3.3.4 不可重写的扩展函数

应为扩展函数是声明在类外部的,转换为java其实就是静态函数,静态函数是属于类,不能被重写,故而不能体现多态.

3.3.5 扩展属性

扩展属性提供一种方法,用来扩展类的API,可以用来访问属性,用的是属性语法而不是函数的语法。尽管它们被视为属性,但它们可以没有任何状态,因为没有合适的地方来存储它,不可能给现有的Java对象的实例添加额外的字段。但有时短语法仍然是便于使用的。

上一节我们定义了lastChar函数,现在我们定义一个lastChar属性

package strings



val String.lastChar: Char

get() = get(this.length - 1)

可以看到,可扩展函数一样,扩展属性也像接收者的一个普通的成员属性一样。这里,必须定义getter函数,因为没有支持字段,因此没有默认getter的实现。同理,初始化也不可以:因为没有地方储存初始值。

声明一个StringBuilder可变得扩展属性,可以置为var

package strings



var StringBuilder.lastChar: Char

get() = get(this.length - 1)

set(value: Char) {

this.setCharAt(length - 1, value)

}

>>>

import strings.lastChar as last



val sb = StringBuilder("Kotlin?")

println(sb.last)

sb.last = '!'

println(sb)

注意,当你需要从Java中访问扩展属性的时候,应该显式的调用它的getter函数

StringUtilKt.getLastChar("Java")

《参考Kotlin实战》

猜你喜欢

转载自blog.csdn.net/cai784921129/article/details/81318867
3.3
今日推荐