首页 > 其他分享 >【Kotlin】扩展属性、扩展函数

【Kotlin】扩展属性、扩展函数

时间:2024-04-08 21:47:23浏览次数:17  
标签:name Kotlin 扩展 var Student fun println 属性

1 类的扩展

​ Kotlin 提供了扩展类或接口的操作,而无需通过类继承或使用装饰器等设计模式,来为某个类添加一些额外的属性或函数,我们只需要通过一个被称为扩展的特殊声明来完成。通过这种机制,我们可以将那些第三方类不具备的功能强行进行扩展,方便我们的操作。

1.1 扩展内置类

1.1.1 扩展属性

fun main() {
    var str = "abc"
    str.property = 5 // 打印: set property, value=5
    var property = str.property // 打印: get property
    println(property) // 打印: 10
}

var String.property: Int
    set(value) {
        println("set property, value=$value")
    }
    get() {
        println("get property")
        return 10
    }

​ 说明:扩展属性并不是真的往类中添加属性,也不会真的插入一个成员字段到类的定义中,导致没有变量存储我们的数据,我们只能明确定义一个 getter 和 setter 来创建扩展属性,才能让它使用起来真的像是类的属性一样。

​ 如下,如果没有定义 getter 和 setter方法,将会报错如下。

img

1.1.2 扩展函数

fun main() {
    var str = "abc"
    str.myFun("xxx") // 打印: myFun, this=abc, value=xxx
}

fun String.myFun(value: String) {
    println("myFun, this=$this, value=$value")
}

1.2 扩展自定义类

1.2.1 扩展属性

1)扩展新属性

fun main() {
    var stu = Student()
    stu.name = "Mary" // 打印: set name, value=Mary
    var name = stu.name // 打印: get name
    println(name) // 打印: Tom
}

class Student

var Student.name: String
    set(value) {
        println("set name, value=$value")
    }
    get() {
        println("get name")
        return "Tom"
    }

2)扩展旧属性

fun main() {
    var stu = Student("Jack")
    stu.name = "Mary" // 无打印
    var name = stu.name // 无打印
    println(name) // 打印: Mary
}

class Student(var name: String)

var Student.name: String // 扩展属性不会生效
    set(value) {
        println("set name, value=$value")
    }
    get() {
        println("get name")
        return "Tom"
    }

​ 说明:如果扩展类中的同名同类型属性,扩展将不会生效。

1.2.2 扩展函数

1)扩展新函数

fun main() {
    var stu = Student("Mary")
    stu.test() // 打印: test, name=Mary
}

class Student(var name: String)

fun Student.test() {
    println("test, name=$name")
}

2)扩展旧函数

fun main() {
    var stu = Student("Mary")
    stu.test() // 打印: inner, name=Mary
}

class Student(var name: String) {
    fun test() {
        println("inner, name=$name")
    }
}

fun Student.test() { // 扩展函数不会生效
    println("extended, name=$name")
}

​ 说明:如果扩展类中的同名同参函数,扩展将不会生效。

1.3 重写父类的扩展函数

​ 类的扩展是静态的,实际上并不会修改它们原本的类,也不会将新成员插入到类中,仅仅是将我们定义的功能变得可调用,使用起来就像真的有一样。同时,在编译时也会明确具体调用的扩展函数。

1.3.1 扩展属性

fun main() {
    var stu: Student = Student()
    var name1 = stu.name // 打印: Student, get name
    println(name1) // 打印: Mary
    var peo: People = stu
    var name2 = peo.name // 打印: People, get name
    println(name2) // 打印: Tom
}

open class People
class Student: People()

var People.name: String
    set(value) {
        println("People, set name, value=$value")
    }
    get() {
        println("People, get name")
        return "Tom"
    }

var Student.name: String
    set(value) {
        println("Student, set name, value=$value")
    }
    get() {
        println("Student, get name")
        return "Mary"
    }

1.3.2 扩展函数

fun main() {
    var stu: Student = Student()
    println(stu.type()) // 打印: Student
    var peo: People = stu
    println(peo.type()) // 打印: People
}

open class People
class Student: People()

fun People.type() = "People"
fun Student.type() = "Student"

1.4 匿名扩展函数

​ 匿名函数的使用详见 →【Kotlin】函数

fun main() {
    var myFun: String.() -> Int = fun String.(): Int {
        return this.length
    }
    println("abc".myFun()) // 打印: 3
}

​ 可以使用 Lambda 表达式简化如下,Lambda 表达式的使用详见 → 【Kotlin】Lambda表达式

fun main() {
    var myFun: String.() -> Int = {
        this.length
    }
    println("abc".myFun()) // 打印: 3
}

1.5 扩展函数作为参数

fun main() {
    var len = "abc".len { this.length }
    println(len) // 打印: 3
}

fun String.len(func: String.() -> Int): Int {
    return func()
}

2 官方扩展函数

2.1 源码

​ Kotlin 提供了一些泛型扩展函数(在 Standard.kt 中),如:apply、also、run、let、takeIf、takeUnless 等。

​ apply、also、run、let 的区别如下,作用是执行 block 函数的内容,并且返回 T 或 block 的返回值,通常用于判空处理。

函数 block是否为扩展函数 block入参 block返回值 函数返回值 访问 T 对象
apply T this
also T T it
run R R this
let T R R it

2.1.1 apply

public inline fun <T> T.apply(block: T.() -> Unit): T {
    ...
    block()
    return this
}

2.1.2 also

public inline fun <T> T.also(block: (T) -> Unit): T {
    ...
    block(this)
    return this
}

2.1.3 run

public inline fun <T, R> T.run(block: T.() -> R): R {
    ...
    return block()
}

2.1.4 let

public inline fun <T, R> T.let(block: (T) -> R): R {
    ...
    return block(this)
}

2.1.5 takeIf

public inline fun <T> T.takeIf(predicate: (T) -> Boolean): T? {
    ...
    return if (predicate(this)) this else null
}

2.1.6 takeUnless

public inline fun <T> T.takeUnless(predicate: (T) -> Boolean): T? {
    ...
    return if (!predicate(this)) this else null
}

2.1.7 with

public inline fun <T, R> with(receiver: T, block: T.() -> R): R {
    ...
    return receiver.block()
}

​ 说明:with 不是扩展函数,但入参 block 是扩展函数。

2.1.8 to

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

2.1.9 toList

public fun <T> Pair<T, T>.toList(): List<T> = listOf(first, second)
public fun <T> Triple<T, T, T>.toList(): List<T> = listOf(first, second, third)

2.2 应用

2.2.1 apply 应用

fun main() {
    var stu = Student()
    test(stu)
}

fun test(stu: Student?) {
    stu?.apply {
        this.name = "Tom"
        this.age = 23
    }
    println(stu) // 打印: [Tom, 23]
}

class Student {
    var name: String? = null
    var age: Int = 0

    override fun toString(): String {
        return "[$name, $age]"
    }
}

​ 说明:also、run、let 的应用与 apply 类似。

2.2.2 takeIf 应用

fun main() {
    var str = "ABC"
    var str2 = str.takeIf { it.length % 2 == 1 }?.let { it + it.reversed().substring(1) }
    println(str2) // 打印: ABCBA
}

2.2.3 with 应用

fun main() {
    var str = "ABC"
    var len = with(str) { this.length }
    println(len) // 打印: 3
}

​ 声明:本文转自【Kotlin】扩展属性、扩展函数

标签:name,Kotlin,扩展,var,Student,fun,println,属性
From: https://www.cnblogs.com/zhyan8/p/18115112

相关文章

  • 有关软件质量一级属性科技论文(4)
    一、软件质量属性软件质量属性,也称软件评估属性,是系统架构设计师必须掌握的核心知识点之一,这些质量属性的具体含义是:(1)性能(Performance)效率指标,是指系统的响应能力,处理任务所需时间或单位时间内的处理量。(2)可靠性(Reliability)是指软件系统在应用或错误面前,在意外或错误使用的......
  • 有关软件质量一级属性科技论文(5)
    开发高质量的软件是一件极具挑战的工作。其中一个重要的原因就是对于“质量”的定义各不相同,变化莫测。而软件架构的设计主要就是围绕满足功能要求和非功能要求,其中的非功能要求就是软件的各种质量属性。杰拉尔德温伯格在他的四部曲巨作《质量软件管理》的第一卷第一章中就谈到了......
  • 软件质量一级属性科技论文(1)
    软件质量概述的六大属性摘要:软件属性包括功能属性和质量属性,但是,软件架构(及软件架构设计师)重点关注的是质量属性。文章从常见的六个质量属性,即可用性、可修改性、性能、安全性、可测试性、易用性写起,使读者对其有初步的认识和了解。关键词:软件;质量属性;体系架构;Sixattributeso......
  • 有关软件质量一级属性科技论文(3)
    五、可测试性可测试性战术的目标是允许在完成软件开发的一个增量后,轻松地对软件进行测试,从而发现错误。可测试性战术分析:1、管理输入/输出(1)记录/回放。指将捕获跨接口地信息,并将其作为测试专用软件地输入。(2)将接口与现实分离。将接口与实现分离允许实现的代替。(3)特化访问路......
  • 软件质量的一级属性科技论文(2)
    三、性能性能反应的是系统的响应能力,表现在三个方面,速度、吞吐量和持续高速性。性能战术的目标是对一定的时间限制内到达系统的事件生成一个响应,这些事件可以是消息到达、定时器到时,系统状态的变化。影响响应时间的因素,包括资源消耗和闭锁时间。资源包括CPU、数据存储、网络通......
  • 5个不必要的VS Code扩展,你早该删了它
    你能数一下你现在有多少VS代码扩展吗?开的越多,平时越慢。目前有大量的扩展提供了VSCode已经内置的功能,它们是在功能还没有添加的时候启用的,但是现在已经变成了累赘。1.AutoCloseHTML/XMLTag当您添加新的HTML标记时,此功能会自动添加相应的结束标记。这些扩展为VS......
  • 通过滤镜filter属性hue-rotate变换主题的方案
    主题切换方案一般都是依赖Css变量去做,但是可以通过滤镜属性可以实现主题色的变换;1,hue-rotate属性,用于调整元素的色相,色相的概念可以在HSL中看到H:色相S:饱和度L:亮度body{filter:hue-rotate(45deg);}成本几乎为0,实现简单。缺点是对于某些图片或者不想改的颜色需......
  • 字符串的扩展
    字符串的扩展字符的Unicode表示法ES6加强了对Unicode的支持,允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的Unicode码点。但是,这种表示法只限于码点在\u0000~\uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表示"\uD842\uDFB7"//"......
  • 正则的扩展
    正则的扩展RegExp构造函数在ES5中,RegExp构造函数的参数有两种情况第一种情况是,参数是字符串,这时第二个参数表示正则表达式的修饰符(flag)varregex=newRegExp('xyz','i');//等价于varregex=/xyz/i;参数是一个正则表示式,这时会返回一个原有正则表达式的拷贝......
  • 函数的扩展
    函数的扩展函数参数的默认值ES6允许为函数的参数设置默认值,即直接写在参数定义的后面。functionlog(x,y='World'){console.log(x,y);}log('Hello')//HelloWorldlog('Hello','China')//HelloChinalog('Hello','')//Hello......