User-Profile-Image
hankin
  • 5
  • Java
  • Kotlin
  • Spring
  • Web
  • SQL
  • MegaData
  • More
  • Experience
  • Enamiĝu al vi
  • 分类
    • Zuul
    • Zookeeper
    • XML
    • WebSocket
    • Web Notes
    • Web
    • Vue
    • Thymeleaf
    • SQL Server
    • SQL Notes
    • SQL
    • SpringSecurity
    • SpringMVC
    • SpringJPA
    • SpringCloud
    • SpringBoot
    • Spring Notes
    • Spring
    • Servlet
    • Ribbon
    • Redis
    • RabbitMQ
    • Python
    • PostgreSQL
    • OAuth2
    • NOSQL
    • Netty
    • MySQL
    • MyBatis
    • More
    • MinIO
    • MegaData
    • Maven
    • LoadBalancer
    • Kotlin Notes
    • Kotlin
    • Kafka
    • jQuery
    • JavaScript
    • Java Notes
    • Java
    • Hystrix
    • Git
    • Gateway
    • Freemarker
    • Feign
    • Eureka
    • ElasticSearch
    • Docker
    • Consul
    • Ajax
    • ActiveMQ
  • 页面
    • 归档
    • 摘要
    • 杂图
    • 问题随笔
  • 友链
    • Spring Cloud Alibaba
    • Spring Cloud Alibaba - 指南
    • Spring Cloud
    • Nacos
    • Docker
    • ElasticSearch
    • Kotlin中文版
    • Kotlin易百
    • KotlinWeb3
    • KotlinNhooo
    • 前端开源搜索
    • Ktorm ORM
    • Ktorm-KSP
    • Ebean ORM
    • Maven
    • 江南一点雨
    • 江南国际站
    • 设计模式
    • 熊猫大佬
    • java学习
    • kotlin函数查询
    • Istio 服务网格
    • istio
    • Ktor 异步 Web 框架
    • PostGis
    • kuangstudy
    • 源码地图
    • it教程吧
    • Arthas-JVM调优
    • Electron
    • bugstack虫洞栈
    • github大佬宝典
    • Sa-Token
    • 前端技术胖
    • bennyhuo-Kt大佬
    • Rickiyang博客
    • 李大辉大佬博客
    • KOIN
    • SQLDelight
    • Exposed-Kt-ORM
    • Javalin—Web 框架
    • http4k—HTTP包
    • 爱威尔大佬
    • 小土豆
    • 小胖哥安全框架
    • 负雪明烛刷题
    • Kotlin-FP-Arrow
    • Lua参考手册
    • 美团文章
    • Java 全栈知识体系
    • 尼恩架构师学习
    • 现代 JavaScript 教程
    • GO相关文档
    • Go学习导航
    • GoCN社区
    • GO极客兔兔-案例
    • 讯飞星火GPT
    • Hollis博客
    • PostgreSQL德哥
    • 优质博客推荐
    • 半兽人大佬
    • 系列教程
    • PostgreSQL文章
    • 云原生资料库
    • 并发博客大佬
Help?

Please contact us on our email for need any support

Support
    首页   ›   Kotlin   ›   Kotlin Notes   ›   正文
Kotlin Notes

Kotlin-类型进阶—内联类(二十七)

2021-01-28 00:57:10
658  0 0
参考目录 隐藏
1) 内联类
2) 内联类的成员
3) 内联类的继承
4) 模拟枚举类
5) 内联类与类型别名

阅读完需:约 4 分钟

内联类

有时候,业务逻辑需要围绕某种类型创建包装器。然而,由于额外的堆内存分配问题,它会引入运行时的性能开销。此外,如果被包装的类型是原生类型,性能的损失是很糟糕的,因为原生类型通常在运行时就进行了大量优化,然而他们的包装器却没有得到任何特殊的处理。

为了解决这类问题,Kotlin 引入了一种被称为 内联类 的特殊类,它通过在类的前面定义一个 inline 修饰符来声明:

inline class Password(val value: String)

内联类必须拥有唯一的一个属性, 并在主构造器中初始化这个属性. 在运行期, 会使用这个唯一的属性来表达内联类的实例

inline class Password(val value: String)

// 'Password' 类的实例不会真实存在
// 在运行期, 'securePassword' 只包含 'String'
val securePassword = Password("Don't try this in production")

这就是内联类的主要功能, 受 “内联” 这个名称的启发而来: 类中的数据被 “内联” 到使用它的地方 (类似于 内联函数 的内容被内联到调用它的地方).


内联类的成员

内联类支持与通常的类相同的功能. 具体来说, 内联类可以声明属性和函数:

inline class Name(val s: String) {
    val length: Int
        get() = s.length

    fun greet() {
        println("Hello, $s")
    }
}

fun main() {
    val name = Name("Kotlin")
    name.greet() // 方法 `greet` 会作为静态方法来调用
    println(name.length) // 属性的取值函数会作为静态方法来调用
}

但是, 对于内联类的成员存在一些限制:

  1. 内联类不能拥有 init 代码段
  2. 内联类的属性不能拥有 后端域变量back field因此, 内联类只能拥有简单的计算属性 (不能拥有延迟初始化属性或委托属性)

内联类的继承

内联类只允许继承接口

interface Printable {
    fun prettyPrint(): String
}

inline class Name(val s: String) : Printable {
    override fun prettyPrint(): String = "Let's $s!"
}    

fun main() {
    val name = Name("Kotlin")
    println(name.prettyPrint()) // 仍然是调用静态方法
}
  1. 内联类不能继承其他类
  2. 内联类是 final 类, 不能被其他类继承


模拟枚举类

内联类也可以用来模拟枚举类,与枚举相比内存占用小,但使用方式类似

inline class State(val ordinal: Int) {
    companion object {
        val Idle = State(0)
        val Busy = State(1)
    }

    fun values() = arrayOf(Idle, Busy)

    val name: String
        get() = when (this) {
            State.Idle -> "Idle"
            State.Busy -> "Busy"
            else -> throw  IllegalArgumentException()
        }
}

inline class Color(val value: UInt) {
    companion object {
        val Red = Color(0xFFFF0000u)
        val Green = Color(0xFF00FF00u)
        val Blue = Color(0xFF0000FFu)
    }

    fun values() = arrayOf(Red, Green, Blue)

    val name: String
        get() = when (this) {
            Red -> "Red"
            Green -> "Green"
            Blue -> "Blue"
            else -> throw  IllegalArgumentException()
        }
}

fun main() {
    State.Busy
    Color.Blue

    var boxInt = BoxInt(5)
    if(boxInt < 10){
        println("value is less than 10")
    }

    val newValue = boxInt.value * 200
    println(newValue)
    boxInt++
    println(boxInt)
}

内联类与类型别名

初看起来, 内联类好像非常象 类型别名. 确实, 它们都声明了一个新的类型, 并且在运行期都表达为各自的底层类型.

但是, 主要的差别在于, 类型别名与它的底层类型是 赋值兼容 的 (与同一个底层类型的另一个类型别名, 也是兼容的), 而内联类不是如此.

也就是说, 内联类会生成一个真正的 新 类型, 相反, 类型别名只是给既有的类型定义了一个新的名字(也就是别名):

typealias NameTypeAlias = String
inline class NameInlineClass(val s: String)

fun acceptString(s: String) {}
fun acceptNameTypeAlias(n: NameTypeAlias) {}
fun acceptNameInlineClass(p: NameInlineClass) {}

fun main() {
    val nameAlias: NameTypeAlias = ""
    val nameInlineClass: NameInlineClass = NameInlineClass("")
    val string: String = ""

    acceptString(nameAlias) // 正确: 需要底层类型的地方, 可以传入类型别名
    acceptString(nameInlineClass) // 错误: 需要底层类型的地方, 不能传入内联类

    // 反过来:
    acceptNameTypeAlias(string) // 正确: 需要类型别名的地方, 可以传入底层类型
    acceptNameInlineClass(string) // 错误: 需要内联类的地方, 不能传入底层类型
}

如本文“对您有用”,欢迎随意打赏作者,让我们坚持创作!

0 打赏
Enamiĝu al vi
不要为明天忧虑.因为明天自有明天的忧虑.一天的难处一天当就够了。
543文章 68评论 294点赞 593545浏览

随机文章
ElasticSearch—映射参数详解(十二)
5年前
java—stream()方法的使用(java8)
5年前
lombok基本注解
5年前
Mybatis—插入数据后返回自增主键ID
4年前
SpringSecurity—基础知识点与流程介绍
5年前
博客统计
  • 日志总数:543 篇
  • 评论数目:68 条
  • 建站日期:2020-03-06
  • 运行天数:1927 天
  • 标签总数:23 个
  • 最后更新:2024-12-20
Copyright © 2025 网站备案号: 浙ICP备20017730号 身体没有灵魂是死的,信心没有行为也是死的。
主页
页面
  • 归档
  • 摘要
  • 杂图
  • 问题随笔
博主
Enamiĝu al vi
Enamiĝu al vi 管理员
To be, or not to be
543 文章 68 评论 593545 浏览
测试
测试
看板娘
赞赏作者

请通过微信、支付宝 APP 扫一扫

感谢您对作者的支持!

 支付宝 微信支付