前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >kotlin--扩展

kotlin--扩展

作者头像
aruba
发布2021-12-06 17:19:39
3180
发布2021-12-06 17:19:39
举报
文章被收录于专栏:android技术
之间使用了kotlin的标准函数、匿名函数,觉得它十分灵活,简便。其实kotlin的标准函数就是用了扩展
一、扩展函数
1.定义扩展函数

当我们需要对一个类新增一个方法时,在Java中需要写一个子类继承它,然后添加我们的新方法。 在kotlin中,可以利用扩展增加类的功能,指定类名后就可以新增函数 我们给所有类新增打印函数,给String新增加上!的方法:

代码语言:javascript
复制
//给所有类新增打印函数 :Any.函数名()
fun Any.print() = println(this)

//给String新增加上!的方法
fun String.addExt(count: Int) = this + "!".repeat(count)

fun main() {
    "abc".print().print()
}
2.泛型扩展函数

如果想要链式调用我们刚刚新增的函数,先调用下打印,再调用新增!,最后再调用打印是不行的

代码语言:javascript
复制
fun main() {
    "abc".print().addExt(5).print()
}

由于print的返回是Any类,但是addExt函数只有String类才有,所以我们需要将print的返回改为String类,但是我又想保持所有类都有print函数,那怎么办呢? 答案是将print函数返回泛型类型,哪个类调用的就返回哪个类

代码语言:javascript
复制
//定义泛型类型扩展函数
fun <T> T.print(): T {
    println(this)
    return this
}

//给String新增加上!的方法
fun String.addExt(count: Int) = this + "!".repeat(count)

fun main() {
    "abc".print().addExt(5).print()
}

结果: abc abc!!!!!

泛型扩展函数在标准函数中随处可见,比如let

代码语言:javascript
复制
public inline fun <T, R> T.let(block: (T) -> R): R {
    contract {
        callsInPlace(block, InvocationKind.EXACTLY_ONCE)
    }
    return block(this)
}
二、扩展属性
1.除了给类扩展函数外,也可以扩展属性

String新增属性,计数元音个数:

代码语言:javascript
复制
//String新增属性,计数元音个数
val String.count
    get() = this.count{ "auieoy".contains(it) }

fun main() {
    "The people's Republic of China".count.print()
}
2.扩展函数也可以定义于可空类型

可以直接在扩展函数内部处理空的情况

代码语言:javascript
复制
fun String?.printDefault(default: String) = print(this ?: default)

fun main() {
    val s: String? = null
    s.printDefault("123")
}
3.infix

infix适用于单个入参的扩展函数,可以使语法更简洁,调用方法时的.和()都可以去除

代码语言:javascript
复制
infix fun String?.printDefault(default: String) = print(this ?: default)

fun main() {
    val s: String? = null
    s printDefault "123"
}
4.扩展文件

为了统一管理,如果想要在多个文件使用扩展函数,可以将它定义在一个单独文件里 定义一个随机函数:

代码语言:javascript
复制
package com.aruba.mykotlinapplication.extension

/**

 * Created by aruba on 2021/8/25.

 */
inline fun <T> Iterable<T>.randomTake() = shuffled().first()

别的文件使用import导入:

代码语言:javascript
复制
import com.aruba.mykotlinapplication.extension.randomTake

fun main() {
    println(listOf(4, 7, 9).randomTake())
}
5.重命名扩展

可以使用as关键字重命名它的名字

代码语言:javascript
复制
import com.aruba.mykotlinapplication.extension.randomTake as random

fun main() {
    println(listOf(4, 7, 9).random())
}
三、DSL
apply函数中,匿名函数中我们可以直接调用接收者的方法,像这种编程范式,业界称为”领域特定语言“,以暴露接收者的函数和特性,以便在lambda中调用和配置它们

apply函数它的实现就是泛型扩展匿名函数 之前我们已经知道如何定义一个匿名函数,现在来定义一个接受匿名函数,返回泛型类型的函数:

代码语言:javascript
复制
fun main() {
    println(getInfo { "123" })
}

fun <T> getInfo(funp: () -> T): T {
    return funp()
}

现在我们想使getInfo函数中,支持DSL,首先需要getInfo函数支持扩展,并且它入参的匿名函数作用域可以直接使用接收者的函数和属性 1.getInfo函数支持扩展 很简单,直接使用T.getInfo()就可以实现 2.作用域可以直接使用接收者的函数和属性,也是扩展的特性,反观下我们上面写的扩展中,函数里使用的this就是接收者,所以扩展函数中,可以直接使用接收者的函数和属性 想要入参的匿名函数作用域可以直接使用接收者的函数和属性,就需要匿名函数支持扩展:

代码语言:javascript
复制
fun main() {
    println("abc".getInfo {
        this + "123"
    })
}

inline fun <T> T.getInfo(funp: T.() -> T): T {
    funp()
    return this
}

如果重复使用该方法,将会创建很多内存,所以我们需要使用inline关键字

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/8/25 下,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 之间使用了kotlin的标准函数、匿名函数,觉得它十分灵活,简便。其实kotlin的标准函数就是用了扩展
  • 一、扩展函数
    • 1.定义扩展函数
      • 2.泛型扩展函数
      • 二、扩展属性
        • 1.除了给类扩展函数外,也可以扩展属性
          • 2.扩展函数也可以定义于可空类型
            • 3.infix
              • 4.扩展文件
                • 5.重命名扩展
                • 三、DSL
                  • apply函数中,匿名函数中我们可以直接调用接收者的方法,像这种编程范式,业界称为”领域特定语言“,以暴露接收者的函数和特性,以便在lambda中调用和配置它们
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档