Kotlin中嵌套类、数据类、枚举类和密封类的详解

简介: Kotlin中嵌套类、数据类、枚举类和密封类的详解

一、嵌套类

如果一个类只对另一个类有用,那么将其嵌入到该类中并使这两个类保持在一起是合乎逻辑的,可以使用

class Player2 {
    /**
     * 嵌套类
     * 如果一个类只对另一个类有用,那么将其嵌入到该类中并使这两个类保持在一起是合乎逻辑的,可以使用
     * 嵌套类。
     */
    class Equipment(var name: String) {
        fun show() = println("equipment:$name")
    }
    fun battle() {
    }
}
fun main() {
    Player2.Equipment("sharp knife").show()
}

输出结果如下

equipment:sharp knife

二、数据类

/**
 * 数据类
 * 数据类,是专门设计用来存储数据的类
 * 数据类提供了toString的个性化实现
 * ==符号默认情况下,比较对象就是比较它们的引用值,数据类提供了equals和hashCode
 * 的个性化实现。
 */
data class Coordinate(var x: Int, var y: Int, val z: Int) {
    val isInBounds = x > 0 && y > 0
}
fun main() {
    println(Coordinate(10, 20, 30))
    //== 比较的是内容  equals 默认使用的超类Any的实现 === 比较的是引用
    // === 比较的是对象的引用
    println(Coordinate(10, 20, 30) == Coordinate(10, 20, 30))
    val (x, y, z) = Coordinate(10, 20, 30)
    println("$x,$y,$z")
}

输出结果如下

Coordinate(x=10, y=20, z=30)
true
10,20,30

三、数据类中的copy函数

data class Student(var name: String, val age: Int) {
    private val hobby = "music"
    val subject: String
    var score = 0
    init {
        println("initializing student")
        subject = "math"
    }
    constructor(_name: String) : this(_name, 10) {
        score = 10
    }
    override fun toString(): String {
        return "Student(name='$name', age=$age, hobby='$hobby', subject='$subject', score=$score)"
    }
}
fun main() {
    val student = Student("jack")
    /**
     * copy
     * 除了重写Any类的部分函数,提供更好用的默认实现外,数据类还提供了一个函数,它可以用来
     * 方便地复制一个对象。假设你想创建一个Student实例,除了name属性,它拥有和另一个现有Student实例完全一样
     * 的属性值,如果Student是个数据类,那么复制现有Student实例就很简单了,只要调用copy函数,给想修改的属性
     * 传入值参就可以了。
     */
    var copyStudent = student.copy("Rose")
    println(student)
    println(copyStudent)
}

输出结果如下

initializing student
initializing student
Student(name='jack', age=10, hobby='music', subject='math', score=10)
Student(name='Rose', age=10, hobby='music', subject='math', score=0)

四、数据类中的解构声明

class PlayerScore(val experience: Int, val level: Int) {
    /**
     * 解构声明
     * 解构声明的后台实现就是component1、component2等若干个组件函数
     * 让每个函数负责管理你想返回的一个属性数据,如果你定义一个数据类,
     * 它会自动为所有定义在主构造函数的属性添加对应的组件函数。
     */
    operator fun component1() = experience
    operator fun component2() = level
}
fun main() {
    val (x, y) = PlayerScore(10, 20)
    println("$x $y")
}

输出结果如下

10 20

创建一个数据类看一下效果

data class Coordinate(var x: Int, var y: Int, val z: Int) {
    val isInBounds = x > 0 && y > 0
}
fun main() {
    println(Coordinate(10, 20, 30))
    //== 比较的是内容  equals 默认使用的超类Any的实现 === 比较的是引用
    // === 比较的是对象的引用
    println(Coordinate(10, 20, 30) == Coordinate(10, 20, 30))
    val (x, y, z) = Coordinate(10, 20, 30)
    println("$x,$y,$z")
}

输出结果

Coordinate(x=10, y=20, z=30)
true
10,20,30

五、数据类中的运算符重载

data class Coordinate2(var x: Int, var y: Int) {
    val isInBounds = x > 0 && y > 0
    /**
     * 运算符重载
     * 如果要将内置运算符应用在自定义类身上,你必须重写运算符函数,告诉编译器该如何操作自定义类。
     */
    /**
     * plus函数名 对应的操作符为+
     * 把一个对象添加到另一个对象里。
     */
    operator fun plus(other: Coordinate2) = Coordinate2(x + other.x, y + other.y)
}
fun main() {
    val c1 = Coordinate2(10, 20)
    val c2 = Coordinate2(10, 20)
    println(c1 + c2)
}

输出结果如下

Coordinate2(x=20, y=40)

使用数据类的条件

正是因为上述这些特性,你才倾向于用数据类来表示存储数据的简单对象,对于那些经常需要比较,复制或打印自身内容的类,数据类尤其适合它们。然而,一个类要成为数据类,也要符合一定条件。总结下来,主要有三个方面

1.数据类必须有至少带一个参数的主构造函数

2.数据类主构造函数的参数必须是var或者val

3.数据类不能使用abstract、open、sealed和inner修饰符。

六、枚举类

/**
 * 枚举类
 * 枚举类,用来定义常量集合的一种特殊类。
 */
enum class Direction {
    EAST,
    WEST,
    SOUTH,
    NORTH
}
fun main() {
    println(Direction.EAST)
    println(Direction.EAST is Direction)
}
• 15

输出结果如下

EAST
true

七、枚举类中定义函数

/**
 * 枚举类
 * 枚举类,用来定义常量集合的一种特殊类。
 */
enum class Direction2(private val coordinate2: Coordinate2) {
    EAST(Coordinate2(10, 20)),
    WEST(Coordinate2(11, 21)),
    SOUTH(Coordinate2(12, 22)),
    NORTH(Coordinate2(13, 23));
    /**
     * 枚举类也可以定义函数
     */
    fun updateCoordinate2(playerCoordinate: Coordinate2) = Coordinate2(playerCoordinate.x + coordinate2.x, playerCoordinate.y + coordinate2.y)
}
fun main() {
    println(Direction2.EAST.updateCoordinate2(Coordinate2(10, 20)))
}

输出结果

Coordinate2(x=20, y=40)

八、代数数据类型

/**
 * 代数数据类型
 * 可以用来表示一组子类型的闭集,枚举类就是一种简单的ADT(抽象数据类型)
 */
enum class LicenseStatus {
    UNQUALIFIED,
    LEARNING,
    QUALIFIED;
}
class Driver(var status: LicenseStatus) {
    fun checkLicense(): String {
        return when (status) {
            LicenseStatus.UNQUALIFIED -> "没资格"
            LicenseStatus.LEARNING -> "在学"
            LicenseStatus.QUALIFIED -> "有资格"
        }
    }
}
fun main() {
    println(Driver(LicenseStatus.QUALIFIED).checkLicense())
}

输出结果如下

有资格

九、密封类的详解

/**
 * 密封类
 * 对于更复杂的ADT(抽象数据类型),你可以使用kotlin的密封类(sealed class)来实现更复杂的定义
 * 密封类可以用来定义一个类似于枚举类的ADT,但你可以更灵活地控制某个子类型。
 * 密封类可以有若干个子类,要继承密封类,这些子类必须和它定义在同一个文件里。
 */
sealed class LicenseStatus2 {
    object UNQUALIFIED : LicenseStatus2()
    object LEARNING : LicenseStatus2()
    class QUALIFIED(val licenseId: String) : LicenseStatus2()
}
class Driver2(var status: LicenseStatus2) {
    fun checkLicense(): String {
        return when (status) {
            is LicenseStatus2.UNQUALIFIED -> "没资格"
            is LicenseStatus2.LEARNING -> "在学"
            is LicenseStatus2.QUALIFIED -> "有资格,驾驶证编号:${(this.status as LicenseStatus2.QUALIFIED).licenseId}"
        }
    }
}
fun main() {
    val status = LicenseStatus2.LEARNING
    val driver2 = Driver2(status)
    println(driver2.checkLicense())
    val status1 = LicenseStatus2.QUALIFIED("809987")
    val driver = Driver2(status1)
    println(driver.checkLicense())
}

输出结果如下

在学
有资格,驾驶证编号:809987


目录
相关文章
|
7月前
|
分布式计算 Java 数据安全/隐私保护
Kotlin 学习笔记(二)—— 数据类、枚举类、循环、常用集合及操作符的写法(下 )
Kotlin 学习笔记(二)—— 数据类、枚举类、循环、常用集合及操作符的写法(下)
35 0
|
7月前
|
Java Kotlin
Kotlin 学习笔记(二)—— 数据类、枚举类、循环、常用集合及操作符的写法(上)
Kotlin 学习笔记(二)—— 数据类、枚举类、循环、常用集合及操作符的写法(上)
33 0
|
9月前
|
安全 Java 编译器
Kotlin 学习笔记(一)—— 基本类型、函数、lambda、类与对象的写法
Kotlin 作为 Android 开发的首选语言,其基础语法和特性需要重点学习。本文概括总结了 Kotlin 的基本类型、关键字、函数、闭包、高阶函数、类与对象等核心知识点,并给出示例代码进行讲解。
154 0
Kotlin 学习笔记(一)—— 基本类型、函数、lambda、类与对象的写法
|
12月前
|
安全 Java 编译器
3 亿美元的 bug,Kotlin 帮你避免 | 内联类 value class
3 亿美元的 bug,Kotlin 帮你避免 | 内联类 value class
93 0
|
2天前
|
移动开发 API Android开发
构建高效Android应用:Kotlin协程的实践指南
【5月更文挑战第11天】 在移动开发领域,性能优化和资源管理是至关重要的。特别地,对于Android开发者来说,合理利用Kotlin协程可以极大地改善应用的响应性和稳定性。本文将深入探讨Kotlin协程在Android中的实际应用,包括它们如何简化异步编程模型、提高UI线程的响应性,以及减少内存消耗。我们将通过具体案例分析,了解如何在实际项目中有效地使用协程,从而帮助开发者构建更加高效的Android应用程序。
|
1天前
|
安全 Java Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【5月更文挑战第16天】 在移动开发领域,性能一直是开发者关注的焦点。随着Kotlin语言的普及,其与Java在Android应用中的性能表现成为热门话题。本文将深入分析Kotlin和Java在Android平台上的性能差异,并通过实际测试数据来揭示二者在编译速度、应用启动时间以及运行效率方面的表现。我们的目标是为开发者提供一个参考依据,以便在选择合适的编程语言时做出更加明智的决策。
|
2天前
|
移动开发 数据处理 Android开发
构建高效Android应用:Kotlin协程的实践与优化策略
【5月更文挑战第14天】在移动开发领域,性能优化和资源管理是提升用户体验的关键因素之一。随着Kotlin语言的普及,其异步编程解决方案——协程,已经成为Android开发者手中的强大工具。本文将深入探讨Kotlin协程在Android应用中的实践方法,分析其在处理异步任务时带来的优势,并提出一系列优化策略,帮助开发者构建更加高效、响应迅速的Android应用。通过具体案例分析和性能对比,我们将展示如何充分利用协程来简化代码结构,提高应用性能,并确保用户界面的流畅性。
|
2天前
|
移动开发 数据库 Android开发
构建高效Android应用:探究Kotlin协程的优势与实践
【5月更文挑战第14天】在移动开发领域,性能优化和流畅的用户体验始终是开发者追求的目标。随着Kotlin语言的兴起,其提供的协程特性为Android应用带来了革新性的异步编程解决方案。本文将深入探讨Kotlin协程的核心优势,并结合实际案例分析如何在Android应用中有效地利用协程来提升性能和响应性,同时保证代码的简洁性和可维护性。
|
2天前
|
移动开发 Android开发 开发者
构建高效Android应用:探究Kotlin协程的优化实践
【5月更文挑战第13天】 在移动开发领域,Android平台的流畅体验至关重要。随着Kotlin语言的普及,协程作为其核心特性之一,为异步编程提供了简洁且高效的解决方案。本文将深入探讨Kotlin协程在Android应用中的优化使用,从基本概念到实际案例分析,旨在帮助开发者构建更加响应迅速、性能卓越的应用。我们将通过对比传统线程与协程的差异,展示如何利用协程简化代码结构,并通过优化实践减少资源消耗,提升用户体验。
|
2天前
|
移动开发 监控 Android开发
构建高效Android应用:Kotlin协程的实践与优化
【5月更文挑战第12天】 在移动开发领域,性能与响应性是衡量一个应用程序优劣的关键指标。特别是在Android平台上,由于设备的多样性和系统资源的限制,开发者需要精心编写代码以确保应用流畅运行。近年来,Kotlin语言因其简洁性和功能性而广受欢迎,尤其是其协程特性,为异步编程提供了强大而轻量级的解决方案。本文将深入探讨如何在Android应用中使用Kotlin协程来提升性能,以及如何针对实际问题进行优化,确保应用的高效稳定执行。