【Kotlin 初学者】扩展-享受编程

网友投稿 647 2022-05-30

一、介绍

Kotlin 可以对一个类的属性和函数进行扩展,且不需要继承或使用 Decorator 模式。

扩展是一种静态行为,对被扩展的类代码本身不会造成任何影响。

二、扩展函数

扩展函数可以在已有类中添加新的函数,不会对原类做修改。

2.1 定义扩展函数

扩展可以用于自定义类,也可以用于比如List、String,以及Kotlin标准库里的其他类。和继承相似,扩展也能共享类行为,在你无法接触某个类定义,或者某个类没有使用open修饰符,导致你无法继承它时,扩展就是增加类功能的最好选择。

//定义School类的扩展函数 fun School.student():String{ return "$name-学习知识" }

School:表示函数的接收者,也就是函数扩展的对象

student:扩展函数的名称

String:返回类型("$name-学习知识")

一、介绍

Kotlin 可以对一个类的属性和函数进行扩展,且不需要继承或使用 Decorator 模式。

扩展是一种静态行为,对被扩展的类代码本身不会造成任何影响。

二、扩展函数

扩展函数可以在已有类中添加新的函数,不会对原类做修改。

2.1 定义扩展函数

扩展可以用于自定义类,也可以用于比如List、String,以及Kotlin标准库里的其他类。和继承相似,扩展也能共享类行为,在你无法接触某个类定义,或者某个类没有使用open修饰符,导致你无法继承它时,扩展就是增加类功能的最好选择。

//定义School类的扩展函数 fun School.student():String{ return "$name-学习知识" }

School:表示函数的接收者,也就是函数扩展的对象

School:表示函数的接收者,也就是函数扩展的对象

student:扩展函数的名称

student:扩展函数的名称

String:返回类型("$name-学习知识")

String:返回类型("$name-学习知识")

其他的就和定义一般函数类似了。

2.1.1 定义School类

class School(var name:String){ //自带函数 fun teacher():String{ return "$name-教书育人" } }

2.1.2 扩展函数

//定义School类的扩展函数 fun School.student():String{ return "$name-学习知识" } //定义String类的扩展函数 fun String.addSC():String{ return "$this-帅次" } fun main() { //School类原来的函数 println(School("超神学院").teacher())//超神学院-教书育人 //School类的扩展函数 println(School("超神学院").student())//超神学院-学习知识 //String类的扩展函数 println("Kotlin".addSC())//Kotlin-帅次 }

2.1.3 扩展函数支持范围

扩展函数定义后在同一个包下可直接调用,在其他包下则需要导入定义的扩展函数。在extension包下定义的扩展函数,在classkotlin包中使用。

同一包下不能定义同名扩展函数。

import com.scc.kotlin.primary.extension.School import com.scc.kotlin.primary.extension.addSC import com.scc.kotlin.primary.extension.student fun main() { println(School("Class包下").student())//Class包下-学习知识 println("ClassKotlin".addSC())//ClassKotlin-帅次 }

在多个包下定义扩展函数addSC(),调用时:

2.1.4 定义超类(Any)扩展函数

因为Any是超类,所以它的扩展函数其他类也能直接使用。这个功能是真的强大。

//定义Any扩展函数 fun Any.eat(): Any { return this } fun main() { //因为Any是超类,所以它的扩展函数其他类也能直接使用 println("超类".eat())//超类 println(15.eat())//15 }

"超类".eat().addSC() 报错

//报错,因为addSC()函数是String类的扩展函数,Any类无法直接调用 //除非将 "超类".eat()的返回类型Any转为String再调用。 "超类".eat().addSC()

这个时候我们该引入泛型扩展函数了。

2.1.5 泛型扩展函数

新的泛型扩展函数不仅可以支持任何类型的接收者,还保留了接收者的类型信息,使用泛型类型后,扩展函数能够支持更多类型的接收者,适用范围更广了。

//定义泛型扩展函数 fun T.scww():T{ return this } fun main() { //WaKa调用泛型扩展函数scww(),返回String类型调用String类型扩展函数addSC() println("WaKa".scww().addSC())//WaKa-帅次 //Int类型15调用泛型扩展函数scww(),返回Int类型调用apply{}函数 println(15.scww().apply { })//15 }

String类型WaKa调用泛型扩展函数scww(),返回String类型调用String类型扩展函数addSC()

Int类型15调用泛型扩展函数scww(),返回Int类型调用apply{}函数

泛型扩展函数在Kotlin标准库里随处可见,例如apply函数,apply函数被定义成了泛型扩展函数,所以能支持任何类型。

public inline fun T.apply(block: T.() -> Unit): T { contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } block() return this }

三、扩展属性

除了给类添加功能扩展函数外,你还可以给类定义扩展属性。

扩展属性允许定义在类或者kotlin文件中,不允许定义在函数中。初始化属性因为属性没有后端字段(backing field),所以不允许被初始化,只能由显式提供的 getter/setter 定义。

扩展属性只能被声明为 val。

//定义扩展属性 //给String类添加一个扩展属性,这个扩展属性可以统计字符长度并加10。 val String.lengthSc get() = this.length.plus(10) //给School类添加个position属性 val School.position get() = "${name}-高级中学" fun main() { println("一二三四五,上山打老虎".lengthSc)//21 println(School("新冠中学").position)//新冠中学-高级中学 }

四、可控类扩展

你也可以定义扩展函数用于可空类型,在可空类型上定义扩展函数,你就可以直接在扩展函数体内解决可能出现的空值问题。

//可空类扩展 //当String为null时打印四大皆空-default fun String?.nullWithDefault(default: String) { println(this ?: "四大皆空-$default") } //当School为null时,打印default-学校没了 fun School?.dropOut(default: String) { println(this ?: "$default-学校没了") } fun main() { var str: String? = null str.nullWithDefault("空空")//四大皆空-空空 str = "数据已到" str.nullWithDefault("空空")//数据已到 var school: School? = null school.dropOut("没得名字")//没得名字-学校没了 school = School("帅次学院") school.dropOut("默认退学")//com.scc.kotlin.primary.extension.School@19dfb72a }

infix 关键字

infix关键字适用于有单个参数的扩展和类函数,可以让你以更简洁的语法调用函数,如果一个函数定义使用了infix关键字,那么调用它时,接收者和函数之间的点操作以及参数的一对括号都可以不要。 (类似 to 函数)

//infix关键字 infix fun String?.nullInfixDefault(default: String){ println(this ?: "Infix-$default") } fun main() { str = null str nullInfixDefault "空值" //Infix-空值 str = "不空" str nullInfixDefault "空值" //不空 //这个就类似mapOf mapOf("Key" to "Value") }

to函数源码

泛型拓展函数、前面加了infix关键字

public infix fun A.to(that: B): Pair = Pair(this, that)

Kotlin标准库中的扩展函数:Kotlin标准库提供的很多功能都是通过扩展函数和扩展属性来实现的,包含类扩展的标准库文件通常都是以类名加s后缀来命名的,例如Sequences.kt,Ranges.kt,Maps.kt。

五、定义扩展文件

扩展函数需要在多个文件里面使用,可以将它定义在单独的文件,然后import。

5.1 定义扩展文件

package com.scc.kotlin.primary.extension //定义扩展文件 fun T.scFile(): T { println("来自ScFile的问候") return this }

5.2 使用

同一包名下的文件调用scFile():

fun main() { str.scFile()//来自ScFile的问候 }

其他包下的文件调用scFile():

import com.scc.kotlin.primary.extension.scFile fun main() { var userInfo4 = UserInfo4() userInfo4.scFile()//来自ScFile的问候 }

5.3 重命名扩展(import文件别名)

import com.scc.kotlin.primary.extension.scFile as scAliasFile fun main() { var userInfo4 = UserInfo4() userInfo4.scAliasFile()//使用新定义的别名,来自ScFile的问候 // userInfo4.scFile()//无法使用,报错 }

六、()->Unit 和 引用类型.()->Unit

package com.scc.kotlin.primary.extension //() -> Unit:普通匿名函数 fun String.doAnonymous(anonymous:() -> Unit):String{ anonymous() return "$this,AnonymousN" } //String.() -> Unit:匿名函数内部this指向一个String对象,隐式调用 fun String.doAnonymousString(anonymous: String.() -> Unit) :String{ println(this) anonymous() return this } //这里使用的泛型匿名函数,使用其内部this fun T.doAnonymousT(anonymous: T.() -> Unit):T { println(this) anonymous() return this } fun main() { //普通匿名函数 "a".doAnonymous{ // println("$this,看看")//此处使用this,报错 } //匿名函数内部this指向一个String对象 "b".doAnonymousString{ println("$this,看看") } 15.doAnonymousT { println("$this,无敌是多么寂寞") } }

DSL

使用这样的编程范式,就可以写出业界知名的“领域特定语言”(DSL),一种API编程范式,暴露接收者的函数和特性,以便于使用你定义的lambda表达式来读取和配置它们。

【Kotlin 初学者】扩展-享受编程

Android android studio Kotlin

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:华为发布城市智能体系列解决方案,深耕城市数字化
下一篇:通过AOP 实现打印全局日志
相关文章