Kotlin的糖真甜:扩展函数和属性

Kotlin一门务实,简洁,安全的编程语言,你值得拥有.

互操作性是Kotlin的设计哲学之一,平滑与现有代码集成是Kotlin的一大特色。如何不重写现有的API的就可以使用Kotlin带来的方便,Kotlin给出的解决方案是扩展函数。理论上讲,扩展函数非常的简单,其实就是一个类的成员函数,但是这个成员函数定义在类的外部。为了更加方便形象的阐述扩展函数,我们添加一个方法用来获取字符串中间的字符:

fun String.middleChar(): Char = this.get(this.length / 2)

为一个类或者接口添加一个扩展函数非常的简单,只需要将类名或接口名放在方法之前并使用. 连接即可。这个类的名称称为接收者类型,用来调用扩展函数的对象称为接收者对象

扩展函数.png

扩展函数的调用和普通的成员调用函数一样:

println("Kotlin".middleChar())

在上面的代码中,String就是接收者类型,“Kotlin”就是接收者对象。

在扩展函数中接收者对象成员可以不用this来访问,上面的方法可以简写成下面的形式:

fun String.middleChar(): Char = get(length / 2)

扩展函数不允许打破被扩展类的封装性,扩展函数不能私有或者受保护的成员。

导入扩展函数

为了避免偶然性的冲突,定义的扩展函数不会自动地在整个项目中生效,如果要使用扩展函数,需要和使用其他任何类和方法一样导入扩展函数,导入的语法没有任何区别。

import strings.middleChar

println("Kotlin".middleChar())

小技巧,在导入多个包类或者方法的时候,如果存在名称冲突可以使用as进行重命名:

import strings.middleChar as mid

println("Kotlin".mid())

Java调用扩展函数

扩展函数实质上是静态函数,调用对象为函数的第一个参数。调用扩展函数,不会创建适配对象也没有任何运行时的额外开销。因此,在Java中调用Kotlin中定义的扩展函数是一件非常简单的事情:调用静态函数,并把接收者对象传递给函数。扩展函数和其他的顶层函数类似,包含这个函数的Java的名称,是由这个函数声明的文件决定的,可以使用@file:JvmName("KotlinStrings") 修改类的名称,在Java中的使用扩展函数:

char mid = KotlinStrings.middleChar("Kotlin");
System.out.println(mid);

扩展函数不可重写

扩展函数并不是类的一部分,扩展函数在类之外声明。可以给父类和子类都定义一个同名的扩展函数,但是在调用时是根据静态类型决定调用的扩展函数而不是运行时类型,下面以一个简单的例子来说明:

open class Base
class Derived : Base()

fun Base.say() {
    println("I am base")
}

fun Derived.say() {
    println("I am derived")
}

fun main(args: Array) {
    val base: Base = Derived()
    base.say()
}

上面的代码将会输出:I am base。

如果成员函数和扩展函数拥有相同的函数签名,优先使用成员函数。

扩展属性

扩展API的另外一种方法是扩展属性,可以用来访问属性,但是使用的属性语法而不是函数语法。尽管称为属性,但是他们没有任何状态,因为没有地方存储。下面以扩展属性的方式实现前面使用的middleChar 函数。

val String.middleChar: Char
    get() = get(length / 2)

扩展属性像类的一个普通属性一样,但是扩展属性必须定义getter函数,这是因为没有支持字段,不会提供默认的getter函数。此外,因为没有存储值的地方,因此扩展属性的初始化是不允许的。

你可能感兴趣的:(Kotlin的糖真甜:扩展函数和属性)