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

news2024/12/23 20:26:57

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方法,将会报错如下。

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 对象
applyTthis
alsoTTit
runRRthis
letTRRit

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.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
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1532440.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Css提高——Css3盒子模型border-box

1、盒子模型的种类与区别 CSS3 中可以通过 box-sizing 来指定盒模型&#xff0c;有2个值&#xff1a;即可指定为 content-box、border-box&#xff0c;这样我们 计算盒子大小的方式就发生了改变。 CSS3 盒子模型 可以分成两种情况&#xff1a; 1. box-sizing: content-box 盒…

智慧安全:守护智慧城市的安全屏障

随着信息技术的迅猛发展&#xff0c;智慧城市已成为现代城市发展的重要方向。智慧城市通过集成应用先进的信息通信技术&#xff0c;实现城市管理、服务、运行的智能化&#xff0c;为城市的可持续发展注入了新的活力。然而&#xff0c;在智慧城市的建设过程中&#xff0c;安全问…

华为openEuler系统卸载jdk

华为openEuler系统卸载jdk 1.查看openEuler上已安装的 Java 版本&#xff1a; 在终端中运行以下命令&#xff0c;查看系统中已经安装的 Java 版本。 sudo alternatives --config java这将列出已安装的 Java 版本&#xff0c;你可以看到当前使用的是哪个版本 2.卸载 Java&am…

SpringCloudAlibaba Nacos配置及应用

Nacos搭建及配置 nacos本机服务搭建 windows上搭建单机nacos&#xff1a; Releases alibaba/nacos GitHub 下载安装包 下载本地&#xff0c;解压&#xff0c;直接运行&#xff08;保证安装包的绝度路径只有英文字符&#xff0c;有中文会导致运行失败&#xff09;&#xff…

测试平台——前端框架

一、创建vue项目 npm init vitelatest web_class wylWYLdeMacBook-Air testplatform % npm init vitelatest web_class ✔ Select a framework: › Vue ✔ Select a variant: › JavaScriptScaffolding project in /Users/wyl/workspace/testplatform/web_class...Done. Now…

【云原生 • Kubernetes】认识 k8s、k8s 架构、核心实战

文章目录 Kubernetes基础概念1. 是什么2. 架构2.1 工作方式2.2 组件架构 3. k8s组件创建集群步骤一 基础环境步骤二 安装kubelet、kubeadm、kubectl步骤三 主节点使用kubeadm引导集群步骤四 副节点加入主节点步骤五 部署dashboard Kubernetes核心实战1. 资源创建方式2. Namespa…

Flink RocksDB状态后端优化总结

截至当前&#xff0c;Flink 作业的状态后端仍然只有 Memory、FileSystem 和 RocksDB 三种可选&#xff0c;且 RocksDB 是状态数据量较大&#xff08;GB 到 TB 级别&#xff09;时的唯一选择。RocksDB 的性能发挥非常仰赖调优&#xff0c;如果全部采用默认配置&#xff0c;读写性…

知乎x-zse-96逆向

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018601872 本文章…

C数据类型(C语言)---变量的类型决定了什么?

目录 数据类型&#xff08;Data Type&#xff09; 变量的类型决定了什么&#xff1f; &#xff08;1&#xff09;不同类型数据占用的内存大小不同 如何计算变量或类型占内存的大小 &#xff08;2&#xff09;不同数据类型的表数范围不同 &#xff08;3&#xff09;不同类型…

【论文阅读】通过组件对齐评估和改进 text-to-SQL 的组合泛化

Measuring and Improving Compositional Generalization in Text-to-SQL via Component Alignment NAACL 2022| CCF B Abstract 在 text-to-SQL 任务中&#xff0c;正如在许多 NLP 中一样&#xff0c;组合泛化是一个重大挑战&#xff1a;神经网络在训练和测试分布不同的情况…

Halcon 3D 平面拟合(区域采样、Z值过滤、平面拟合、平面移动)

Halcon 3D 平面拟合(区域采样、Z值过滤、平面拟合、平面移动) 链接:https://pan.baidu.com/s/1UfFyZ6y-EFq9jy0T_DTJGA 提取码:ewdi * 1.读取图片 ****************

选择word中的表格VBA

打开开发工具 选择Visual Basic插入代码 Sub 选择word中的表格() Dim t As Table an MsgBox("即将选择选区内所有表格&#xff0c;若无选区&#xff0c;则选择全文表格。", vbYesNo, "提示") If an - 6 Then Exit Sub Set rg IIf(Selection.Type wdSel…

FortiGuard Labs:2024网络安全威胁趋势及预测

如今&#xff0c;随着网络犯罪即服务&#xff08;CaaS&#xff09;市场规模的快速增长以及生成式人工智能&#xff08;Generative AI&#xff09;技术的横空出世&#xff0c;网络犯罪分子的攻击手段比以往更加便捷&#xff0c;甚至仅需“一次点击”即可轻松快速发动攻击。如此一…

故障诊断 | 一文解决,GRNN广义回归神经网络的故障诊断(Matlab)

文章目录 效果一览文章概述专栏介绍模型描述源码设计参考资料效果一览 文章概述 故障诊断 | 一文解决,GRNN广义回归神经网络的故障诊断(Matlab) 专栏介绍

Crypto Gladiator League (CGL)

《加密角斗士》是一款完全链上游戏。所有角斗士、装备、代币等的生成过程都可以透明追溯。不可能被篡改或欺骗&#xff0c;使所有游戏物品都是真实资产。 CGL 现已升级为全链游戏平台和 Web3 游戏流量门户&#xff0c;通过多维度收集用户数据&#xff0c;并将数据应用于游戏中&…

手机运营商二要素检测:重塑信任基石,筑牢信息安全屏障

随着移动互联网的普及和数字经济的快速发展&#xff0c;用户信息安全的重要性日益凸显。运营商二要素检测作为一种强大的安全验证机制&#xff0c;以其精准匹配与实时验证的特性&#xff0c;为各类应用场景提供了一种可靠的身份识别解决方案&#xff0c;正在成为众多企业和服务…

Vue3 中应该使用 Ref 还是 Reactive?

一、引言 在Vue 3中&#xff0c;构建响应式数据结构是构建用户界面和交互体验的核心部分。而在创建这些响应式数据时&#xff0c;我们有两个主要工具&#xff1a;reactive和ref。选择使用哪一个&#xff0c;实际上取决于你的数据结构和访问需求。 reactive主要用于处理复杂的数…

初识 Selenium 测试框架

目录 什么是Selenium&#xff1f; Selenium有什么特点&#xff1f; Selenium Webdriver的工作原理什么&#xff1f; Selenium的使用前提 什么是Selenium&#xff1f; Selenium是一个针对web应用&#xff0c;基于UI的自动化的测试框架。 Selenium3.0包括 Selenium IDE&…

2024年第六届区块链与物联网国际会议(BIOTC 2024)即将召开!

2024年第六届区块链与物联网国际会议&#xff08;简称&#xff1a;BIOTC 2024&#xff09;将于2024 年 7 月 19 日至 21 日在日本福冈召开&#xff0c;旨在为来自行业、学术界和政府的研究人员、从业者和专业人士提供一个论坛&#xff0c;就研发区块链和物联网的专业实践进行交…

如何批量开展单因素COX回归分析形成表格?

在统计分析过程中&#xff0c;如果有生存时间数据&#xff0c;那么就需要用到生存分析&#xff0c;COX回归了&#xff01; SPSS进行COX回归的操作简单&#xff0c;输出也快速&#xff0c;但只能逐个选入变量进行单因素回归&#xff0c;我们在实际分析中遇到的往往是多个变量进行…