扩展机制

作者: 航空航天  发布:2019-10-01

由于官网的例子很全面,因此这里直接套用Kotlin官网的例子:

大家好,我是William李梓峰,欢迎加入我的Kotlin学习之旅。
今天是我学习 Kotlin 的第十二天,内容是 Extensions - 扩展机制。

Lambda表达式 和 Extension 是Kotlin语言中两个非常漂亮的语法特性,两者联合起来使用常常会触发许多令人意想不到的化学效应;一旦你也熟悉了这两个语法,很容易爱上他们;

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()   // call the extension function
    }
}

class C1 : C() {
    override fun D.foo() {
        println("D.foo in C1")
    }

    override fun D1.foo() {
        println("D1.foo in C1")
    }
}

C().caller(D())   // prints "D.foo in C"
C1().caller(D())  // prints "D.foo in C1" - dispatch receiver is resolved virtually
C().caller(D1())  // prints "D.foo in C" - extension receiver is resolved statically

下文的 extension 包含多个意思,有的是指扩展机制,有的是指扩展函数和扩展属性,如果遇到难以理解的中文描述,请先看英文原文,欢迎大家勘误校正,一起进步。

Ok, let's start...

例子很简单,无非就是Extension的声明和如何调用Extension方法(注意:这里调用Members' Extension 通过了实例方法的转接,可以跟Kotlin Extension - Method中提到的无法在.kt文件中从实例或者外界直接拿到Extension方法引用联系起来)
这里Kotlin定义了两个重要的概念:

官方文档:

Lambda表达式基础

先来熟悉一下Lambda表达式的基础知识!
Lambda翻译为中文有匿名函数的意思,不过,在Kotlin语言中,有专门的匿名函数语法;所以,二者一定要区分开来,这个知识点将在后面进行讲解。

Lambda表达式和匿名函数本质上依然是一个函数,可以认为是函数的一个变体;所有的函数都可以转换为Lambda表达式,所有的Lambda表达式也可以转换为函数;先看一个简单的例子:

// 这是一个简单的比较数字大小的函数
fun max(i: Int , j: Int): Boolean {
    return i  > j
}
// 转换为Lambda表达式
{i: Int , j: Int -> i > j}

从上面的例子我们很容易了解到Lambda表达式的三个基本要素:

  • 代码块要放在大括号里面
  • 使用->隔离变量和表达式
  • 如果->后面的表达式会产生新的值,这个新值将作为该Lambda表达式的返回值;如果表达式有多行代码,并且有多行代码有返回值,将使用最后一行代码的返回值作为该Lambda表达式的返回值;

在使用过程中记住这三点就可以轻松地使用Lambda表达式;

dispatch receiver: 指的便是例子中执行caller() 方法的C或者C1实例对象
  • https://kotlinlang.org/docs/reference/extensions.html

理解简化版本的Lambda表达式

在日常使用过程中,我们经常可以看到一些极简的Lambda表达式,有些同学可能会误以为是不是代码写错了,或者根本就不是Lambda表达式;其实不然,来看一个简单的例子:

// 1) 简化表达式一
val sum: (Int , Int)->Int = {x , y -> x + y}
// 这个简化的Lambda表达式很容易理解,Kotlin语言支持类型推导,通过前面sum变量指定的参数类型,很容易推导出x,y均为Int类型,故类型参数可以省略掉;
// 2) 简化表达式二
ints.filter { it > 0 }
// 这个简化的Lambda表达式的确有点难以理解,Kotlin语言中有一个约定,如果Lambda表达式的参数只有一个,则可以省略参数声明语句;
// 举一反三
val cl: (Int)->Boolean = {x > 0}
// 这样写是否可以呢?答案是:不可以!
// 目前的Kotlin编译器不支持这样的写法,x必须修改为it;其实,按照逻辑来讲,我认为这样写也是合理的;当然,Kotlin团队可能也是为了规范单一参数Lambda表达式的统一。
extension receiver: 指的便是例子中caller() 方法定义中执行Extension方法foo() 的对象

接下来看看三个例子给我们揭示的一些重要现象

Extensions - 扩展机制

Kotlin, similar to C# and Gosu, provides the ability to extend a class with new functionality without having to inherit from the class or use any type of design pattern such as Decorator.
Kotlin,跟 C# 语言 以及 Gosu 语言 很像。Kotlin 提供了一种新的扩展机制,不用继承或设计模式(例如装饰器模式)。

This is done via special declarations called extensions. Kotlin supports extension functions and extension properties.
这种机制就叫 extensions (这名字一点都不酷炫)。Kotlin 支持函数扩展和属性扩展。(跟 javascript prototype 继承很像的)

匿名函数

Kotlin语言还支持匿名函数,事实上在开发过程中笔者很少使用匿名函数;不过为了保证文章的完整性,这里也做一个简单介绍!
看一个简单的例子:

// 该匿名函数主要用于判断整形x值是否大于0
val f: (Int)->Boolean = fun(x)->x > 0

匿名函数很好理解,即省略了函数名的函数而已!直接在fun关键字后面写形参。
至此,Lambda表达式的基础知识已经讲解完毕;下面开始笔者最喜欢的Kotlin语言特性Extension的讲解。

Extension翻译为中文的意思是扩展,以下简称扩展
扩展特性最早出现在OC语言中,OC的后继者Swift同样支持扩展特性;遗憾的是,在Java语言中,一直到Java1.8,扩展特性依然未获得支持;幸运的是,Kotlin语言支持该特性,Cheers!

本文由金沙澳门官网发布于航空航天,转载请注明出处:扩展机制

关键词: