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

1 类的扩展

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

1.1 扩展内置类

1.1.1 扩展属性

fun main() {var str = "abc"str.property = 5 // 打印: set property, value=5var property = str.property // 打印: get propertyprintln(property) // 打印: 10
}var String.property: Intset(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=Maryvar name = stu.name // 打印: get nameprintln(name) // 打印: Tom
}class Studentvar Student.name: Stringset(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 nameprintln(name1) // 打印: Maryvar peo: People = stuvar name2 = peo.name // 打印: People, get nameprintln(name2) // 打印: Tom
}open class People
class Student: People()var People.name: Stringset(value) {println("People, set name, value=$value")}get() {println("People, get name")return "Tom"}var Student.name: Stringset(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()) // 打印: Studentvar peo: People = stuprintln(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? = nullvar age: Int = 0override 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.rhkb.cn/news/280175.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

爬虫基础:Web网页基础

爬虫基础&#xff1a;Web网页基础 前言Web网页基础网页的组成网页的结构节点树及节点间的关系选择器 前言 用浏览器访问不同的网站时&#xff0c;呈现的页面各不相同&#xff0c;你有没有想过为何会这样呢&#xff1f;了解一下网页的组成、结构和节点等内容。了解这些内容有助于…

如何实现图片上传至服务器

在绝大多数的项目中都会涉及到文件上传等&#xff0c;下面我们来说一下技术派中是如何实现原生图片上传的&#xff0c;这个功能说起来简单&#xff0c;但其实对于技术还是有考验的。图片的上传涉及到IO读写&#xff0c;一个文件上传的功能&#xff0c;就可以把IO流涉及到的知识…

MySQL中的基本SQL语句

MySQL中的基本SQL语句 查看操作 1. 查看有哪些数据库 show databases; 2.切换数据库 use 数据库名;比如切换至 mysql数据库 use mysql;3.查看数据库中的表 show tables;4.查看表中数据 select 要查询的东西 from 表名 [ where 条件 ];select * from 表名…

极简生活|2024年让自己越来越好的18个极简好习惯

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 转眼间已经进入了2024年&#xff0c;新的一年&#xff0c;新的开始。 俗话说&#xff1a;百尺高台起于垒土&#xff0c;千里之堤毁于蚁穴。 好习惯积累的越多&#xff0c;坏习惯越来越少&#xff0c;我们的生活才能越…

echarts饼图图例换行

legend: {left: "5%",bottom: "10%",orient: vertical,}, 完整代码 option {tooltip: {trigger: item},legend: {left: "5%",bottom: "10%",orient: vertical,},// legend: [// {// x: left,// left:"5%",// bottom: …

在Linux环境底下 用C语言执行Python程序

在Linux环境底下 用C语言执行Python程序 文章目录 在Linux环境底下 用C语言执行Python程序1、环境安装&检测2、C语言调用Python语句2.1 直接调用python语句2.2 调用无参python函数2.3 调用有参python函数 1、环境安装&检测 通过C语言调用Python代码&#xff0c;需要先安…

matlab 混沌系统李雅普洛夫指数谱相图分岔图和庞加莱界面

1、内容简介 略 65-可以交流、咨询、答疑 2、内容说明 matlab 混沌系统李雅普洛夫指数谱相图分岔图和庞加莱界面 混沌系统李雅普洛夫指数谱相图分岔图和庞加莱界面 李雅普洛夫指数谱、相图、分岔图、庞加莱界面 3、仿真分析 略 4、参考论文 略

Java基础学习笔记三

环境变量CLASSPATH classpath环境变量是隶属于java语言的&#xff0c;不是windows操作系统的&#xff0c;和PATH环境变量完全不同classpath环境变量是给classloader&#xff08;类加载器&#xff09;指路的java A 。执行后&#xff0c;先启动JVM&#xff0c; JVM启动classload…

目标检测---IOU计算详细解读(IoU、GIoU、DIoU、CIoU、EIOU、Focal-EIOU、SIOU、WIOU)

常见IoU解读与代码实现 一、✒️IoU&#xff08;Intersection over Union&#xff09;1.1 &#x1f525;IoU原理☀️ 优点⚡️缺点 1.2 &#x1f525;IoU计算1.3 &#x1f4cc;IoU代码实现 二、✒️GIoU&#xff08;Generalized IoU&#xff09;2.1 GIoU原理☀️优点⚡️缺点 2…

浏览量这么低,还要不要继续坚持?

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 曾经在一个群里聊天&#xff0c;有群友看到我两位数的浏览量&#xff0c;说到&#xff1a;浏览量这么低还坚持什么&#xff1f; 浏览量低是事实&#xff0c;大多数是十几二十的&#xff0c;上百的都是少数&#xff0c…

ros小问题之差速轮式机器人轮子不显示(rviz gazebo)

在rviz及gazebo练习差速轮式机器人时&#xff0c;很奇怪&#xff0c;只有个机器人的底板及底部的两个万向轮&#xff0c;如下图&#xff0c; 后来查看相关.xacro文件&#xff0c;里面是引用包含了轮子的xacro文件&#xff0c;只需传入不同的参数即可调用生成不同位置的轮子&…

QT网络编程之获取本机网络信息

一.概述 查询一个主机的MAC地址或者IP地址是网络应用中常用到的功能&#xff0c;Qt提供了QHostInfo和QNetworkInterface 类可以用于此类信息的查询 1.QHostInfo 类&#xff08;显示和查找本地的信息&#xff09; 2.QNetworkInterface 类&#xff08;获得应用程序上所在主机的…

猜数字游戏有三变(Java篇)

本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

网络原理(3)——TCP协议

目录 一、连接管理 二、三次握手 1、何为三次握手&#xff1f; 2、三次握手有何意义&#xff1f; 三、四次挥手 三次握手和四次挥手的相似之处和不同之处 &#xff08;1&#xff09;相似之处 &#xff08;2&#xff09;不同之处 四、TCP的状态 建立连接&#xff1a; 断开…

docker一键部署若依前后端分离版本

比如这里把文件放到/xin/docker/jiaoZ/的目录下&#xff0c;jar包和下面的配置文件都放在这个文件夹下。 注意要把jar端口改为你实际启动的&#xff0c;映射端口也可以改为你想要的。 这里的映射端口为&#xff1a;nginx监听80端口&#xff0c;jar在8620端口&#xff0c;mysq…

【matlab安装casadi】

虽然安装起来很简单&#xff0c;但是网上没找到好的教程&#xff0c;姑且写一下记录一下 首先到github找到对应的库&#xff1a;https://github.com/casadi/casadi找到发布的版本&#xff0c;点进去 这里就可以点进去下载自己需要的版本了下面也有对应的下载后的安装方式&…

[python] 卡诺图化简

在温故数据合并的时候突然想起数电的 卡诺图. 根据合并一位不同的原则, 使用 python 做了一个实现, 感觉和QM算法不太一样: # 判断两个数是否只有一个二进制不一样 def nor(x1, x2):return x1^x2# 判断两个集合是否相邻, 只有一位不同 def is_track(x1, x2):ts [nor(x1[i],x…

计算机网络——物理层(编码与调制)

计算机网络——编码与调制 基带信号和宽带信号编码与调制数字数据编码为数字信号非归零编码归零编码反向不归零编码曼彻斯特编码差分曼彻斯特编码4B/5B编码 数字数据调制为模拟信号模拟数据编码为数字信号模拟数据调制为模拟信号 我们之前讲了物理层的一些基础知识和两个准则&a…

腾讯云服务器如何购买省钱?2024年优惠券和优惠活动整理

腾讯云代金券领取渠道有哪些&#xff1f;腾讯云官网可以领取、官方媒体账号可以领取代金券、完成任务可以领取代金券&#xff0c;大家也可以在腾讯云百科蹲守代金券&#xff0c;因为腾讯云代金券领取渠道比较分散&#xff0c;腾讯云百科txybk.com专注汇总优惠代金券领取页面&am…

【数据结构】猛猛干11道链表OJ(未完待续ing)

前言知识点 链表的调试技巧 int main() {struct ListNode* n1(struct ListNode*)malloc(sizeof(struct ListNode));assert(n1);struct ListNode* n2(struct ListNode*)malloc(sizeof(struct ListNode));assert(n2);struct ListNode* n3(struct ListNode*)malloc(sizeof(struc…