有趣的 Kotlin 0x15:data object

news2024/11/15 23:24:08

简介

Kotlin 早在 1.7.20版本就引入了一种新的对象声明类型:data object,但是处于Experimental 阶段 。data object 与常规object 在概念上表现一致,但带有开箱即用且语义清晰的 toString 函数。而在 1.8.20 版本,data class 的语义得到了改进,编译器会自动帮忙生成一些方便的函数:

  • toString
  • equals
  • hashCode

无 copy 和 componentN 函数,这是和 data class 的区别。

基本用法

核心就是提高 object 对象 toString 函数返回值的可读性,特别是针对继承 sealed class 的场景。

开启编译选项

tasks.withType<KotlinCompile> {
    kotlinOptions.languageVersion = "1.9"
}

或者

tasks
    .withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask<*>>()
    .configureEach {
        compilerOptions
            .languageVersion
            .set(
                org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
            )
    }

toString

sealed interface ReadResult
data class Number(val number: Int) : ReadResult
data class Text(val text: String) : ReadResult
data object EndOfFile : ReadResult

fun main() {
    println(Number(7)) // Number(number=7)
    println(EndOfFile) // EndOfFile
}

equals

大多数情况下,data object 对象都是单例,但是在部分极端情况(反射或者序列化等场景)会出现多实例的情况,所以请使用 == 双等号进行结构比较,不要使用三等号的引用比较。

import java.lang.reflect.Constructor

data object MySingleton

fun main() {
    val evilTwin = createInstanceViaReflection()

    println(MySingleton) // MySingleton
    println(evilTwin) // MySingleton

    // Even when a library forcefully creates a second instance of MySingleton, its `equals` method returns true:
    println(MySingleton == evilTwin) // true

    // Do not compare data objects via ===.
    println(MySingleton === evilTwin) // false
}

fun createInstanceViaReflection(): MySingleton {
    // Kotlin reflection does not permit the instantiation of data objects.
    // This creates a new MySingleton instance "by force" (i.e., Java platform reflection)
    // Don't do this yourself!
    return (MySingleton.javaClass.declaredConstructors[0].apply { isAccessible = true } as Constructor<MySingleton>).newInstance()
}

引用不相等

设计动机

data class 会自动帮助开发者生成语义表达能力很强的 toString 方法。但是 object 无此特性,这会导致在 Kotlin 中实现代数数据类型(ADTs)时造成不一致。

sealed class MyList<T> {
    data class Cons<T>(val value: T) : MyList<T>()
    object Nil : MyList<Nothing>()
}

fun main() {
    println(MyList.Cons(42))   // Cons(value=42)
    println(MyList.Nil)        // test.MyList$Nil@1d251891 
}

针对上述问题,开发者目前只能通过两种方式解决:

  • 自行覆写 toString 方法,但是会导致模板代码
    object Nil : MyList<Nothing>() {
        override fun toString(): String {
            return "Nil"
        }
    }
  • 使用带有占位符默认参数的 data class但是代码冗余奇怪且参数无意义
data class Nil(private val placeholder: String = "")

为了更优雅的解决上述问题,data object 应运而生。

sealed class MyList<T> {
    data class Cons<T>(val value: T) : MyList<T>()
    data object Nil : MyList<Nothing>()
}

fun main() {
    println(MyList.Cons(42))   // Cons(value=42)
    println(MyList.Nil)        // Nil
}

总结

新增 data object 后,Kotlin 语言中的 object 一族已经来到 4 位:

  • 常规 object
 object Nil : MyList<Nothing>()
  • companion object
companion object {
    const val TAG = "LearningAndroidOpenCV"
}
  • anonymous object
val helloWorld = object {
    val hello = "Hello"
    val world = "World"
    // object expressions extend Any, so `override` is required on `toString()`
    override fun toString() = "$hello $world"
}
  • data object
data object Nil : MyList<Nothing>()

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

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

相关文章

webstorm 创建harthat项目

Getting started with Hardhat | Ethereum development environment for professionals by Nomic FoundationGetting started with Hardhathttps://hardhat.org/hardhat-runner/docs/getting-started#quick-start安装环境 npm install --save-dev hardhat 创建项目 npx hard…

基数树RadixTree

转自&#xff1a;基数树RadixTree - 知乎 1. 基数树概述 对于长整型数据的映射&#xff0c;如何解决Hash冲突和Hash表大小的设计是一个很头疼的问题。radix树就是针对这种稀疏的长整型数据查找&#xff0c;能快速且节省空间地完成映射。借助于Radix树&#xff0c;我们可以实现…

IntelliJ IDEA Run时报“无效的源发行版:16“错误

在新建Java项目时&#xff0c;run运行main方法时&#xff0c;报错 “java: 错误: 无效的源发行版&#xff1a;16”&#xff0c;了解一番后原来自己创建项目时&#xff0c;Project language level 没有和Project SDK版本相匹配。 还原创建项目步骤&#xff1a; 一、创建项目 …

Python语音增强

img { margin: auto; display: block } 简介 音频时域波形具有以下特征&#xff1a;音调&#xff0c;响度&#xff0c;质量。我们在进行数据增强时&#xff0c;最好只做一些小改动&#xff0c;使得增强数据和源数据存在较小差异即可&#xff0c;切记不能改变原有数据的结构&…

3.0 响应式系统的设计与实现

1、Proxy代理对象 Proxy用于对一个普通对象代理&#xff0c;实现对象的拦截和自定义&#xff0c;如拦截其赋值、枚举、函数调用等。里面包含了很多组捕获器&#xff08;trap&#xff09;&#xff0c;在代理对象执行相应的操作时捕获&#xff0c;然后在内部实现自定义。 const…

将PDF文件转换为JPG格式图片的3种简单方法

如何在线将PDF文件转换成图片格式&#xff1f;如果您在使用PDF文件时只需要其中一页或几页的内容&#xff0c;将PDF转换为图片可以使您更方便地使用这些内容。下面介绍三种简单易用的PDF转图片的方法。 方法一&#xff1a;记灵在线工具 记灵在线工具是一个免费的在线PDF转换工…

方太也造车?

听说方太也造车了&#xff1f; 造车闹剧层出不穷 近年来&#xff0c;随着智能汽车概念的风行&#xff0c;各大品牌也掀起了一股造车的热潮。一时间&#xff0c;互联网、房地产、家电、手机……各行各业的企业都纷纷粉墨登场&#xff0c;各种造车闹剧层出不穷。 然而很快人们就发…

【三十天精通Vue 3】第二十七天 如何用Vue 3和TensorFlow.js实现人脸识别Web应用?

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: 三十天精通 Vue 3 文章目录 引言一、项目简介1.1 概述1.2 功能特点1.3 技术栈二、准备工作2.1 环境搭建2.2 项目初始化2.3 引入依赖

Bus动态刷新

Bus动态刷新全局广播配置实现 启动 EurekaMain7001ConfigcenterMain3344ConfigclientMain3355ConfigclicntMain3366 运维工程师 修改Gitee上配置文件内容&#xff0c;增加版本号发送POST请求curl -X POST "http://localhost:3344/actuator/bus-refresh" —次发送…

【C++进阶之路】第二篇:多态 抽象类 单继承和多继承关系中的虚函数表

&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f; &#x1f36d;&#x1f36d;系列专栏&#xff1a;【C学习与应用】 ✒️✒️本篇内容&#xff1a;多态的概念&#xff0c;多态的构成条件&#xff0c;虚函数重写&#xff0c;C11final和overrid&#xff0c;重…

谈谈我对Edge浏览器分屏功能的使用感受

谈谈我对Edge浏览器分屏功能的使用感受 前言 最近&#xff0c;微软为 Microsoft Edge 浏览器的稳定版本带来了分屏浏览 (Split Screen) 这个新玩意儿&#xff0c;这个功能允许用户在同一个页面以左右视图的形式并排打开两个标签页&#xff0c;类似于软件的分屏。 各位看官如果想…

将经纬度坐标在ArcGIS软件中生成系列矢量数据

目录 环境介绍&#xff1a; 操作内容&#xff1a; 操作步骤&#xff1a; 1、将经纬度坐标值编辑在excel中&#xff0c;注意x、y对应的分别是经度和纬度 2、打开ArcMap软件&#xff0c;加载.xls数据 3、需要选择地理坐标系 4、点矢量数据生成 5、线矢量数据生成 6、面矢量…

2.1 Linux命令行

系列文章目录 第1章 Linux Shell简介 第2章 Shell基础 <本章所在位置> 第3章 Bash Shell基础命令 第4章 Bash Shell命令进阶 第5章 Linux Shell深度理解 第6章 Linux环境变量 第7章 Linux文件权限 第8章 Linux文件系统的管理 第9章 Linux软件安装 第10章 Linux文本编辑器…

Linux多路IO复用:select

1. 多路IO复用 内核监听多个socket文件描述符读写缓冲区属性的变化&#xff0c;若某个文件描述符的读缓冲区有变化&#xff0c;则将该事件告诉应用层。 内核提供多路IO复用的API&#xff1a;select、poll&#xff08;使用较少&#xff09;、epoll。 2. select select原理 用…

设置让Windows每天在指定时间自动关机

其实我们的电脑是可以设置每天在指定的时间点自动关机的&#xff0c;具体操作方法&#xff1a; 1、开打电脑&#xff0c;点击电脑系统左下角windows图标&#xff0c;选择“控制面板”并进入&#xff1b;如图 2、在控制面板界面找到“管理工具”&#xff0c;点击开打&#xff1b…

idea2021.3.x激活教程

第一步: 下载最新的 IDEA 2021.3.3 版本安装包 先从 IDEA 官网下载 IDEA 2021.3.3 版本的安装包&#xff0c;下载链接可以自行百度IDEA官网。 点击下载&#xff0c;耐心等待下载完成。 第二步: 开始安装(已安装可跳过此步骤) 指定安装目录。 勾选创建桌面快捷方式&#xff0…

springboot+java共享厨房租赁信息系统

功能介绍开发环境 springboot是基于spring的快速开发框架, 相比于原生的spring而言, 它通过大量的java config来避免了大量的xml文件, 只需要简单的生成器便能生成一个可以运行的javaweb项目, 是目前最火热的java开发框架 开发语言&#xff1a;Java 框架&#xff1a;springb…

浪潮盒子IPBS9505-多遥控版-S905L/M2芯片-安卓4.4.2-线刷固件包

浪潮盒子IPBS9505-多遥控版-S905L&#xff0f;M2芯片-安卓4.4.2-线刷固件包-内有教程和短接点-当贝纯净桌面。 特点&#xff1a; 1、适用于对应型号的电视盒子刷机&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、修改dns&#xff0c;三网通用&…

微机原理 || 第六章 I/O接口 测试题(答案+解析)

1、下列设备与CPU相连不需要通过接口的是()。 A内存条 B键盘 C U盘. D 硬盘 2、I/O接口电路通常具有()三种端口。 A 数据端口、控制端口、状态端口 (信息分类) 3、以下叙述中&#xff0c;不属于接口功能的是()。 A 提供接口的状态&#xff0c;以便CPU查询 B实现数据格式…

基于vue的毕业生研究生大学生交流学习平台

下面进行系统的功能需求分析。 1.前台功能模块&#xff1a;可以在前台Web浏览器中查看这些功能。 用户注册模块&#xff1a;将用户信息记录到用户表。 用户登录模块&#xff1a;用来区分三种用户&#xff0c;普通用户、普通管理员和超级管理员。 个人信息管理&#xff1a;用户登…