Kotlin知识体系(二) : Kotlin的七个关键特性

前言

在Android开发中,Kotlin以其简洁的语法和强大的特性显著提升了开发效率。本文将解析Kotlin中7个关键特性,通过代码示例展示它们在实际开发中的应用。

一、构造函数:主次分明

主构造函数

kotlin 复制代码
class User constructor(_name: String) { // 传统写法
    val name = _name
}

class Student(val id: Int, var name: String) // 简化版

主构造函数直接声明在类名后,使用val/var声明参数可自动创建属性

次构造函数

kotlin 复制代码
class Person(val name: String) {
    constructor(name: String, age: Int) : this(name) {
        println("Secondary constructor: $name, $age")
    }
}

次构造函数必须委托主构造函数,适用于需要多种初始化方式的场景

二、数据类:样板代码终结者

kotlin 复制代码
data class Book(val id: Int, val title: String, var price: Double)

自动生成功能:

equals()/hashCode()

toString() 格式:Book(id=1, title=Kotlin Guide, price=39.9)

copy() 方法实现对象浅拷贝

• 组件函数componentN()支持解构

大多数情况下,自动生成的equals() / hashCode()都是可靠的。

  • 对于基本类型(Int、String 等):直接比较值。
  • 对于引用类型(其他对象):调用其 equals() 方法。
  • 例外 :数组(Array)的比较使用 Arrays.equals(),而非内容深度比较。(一维数组使用Arrays.Equals()能够实现深度比较,但二位数组使用Array.Equals不能实现深度比较)
    需要干预的场景 :

类体中定义额外属性

  • 继承非data class (用组合代替继承)
  • 二位数组内容的深度比较(得用deepEquals())

三、单例对象:object关键字

kotlin 复制代码
object NetworkManager {
    private const val TIMEOUT = 5000
    
    fun makeRequest(url: String) {
        println("Requesting $url with timeout $TIMEOUT")
    }
}

// 使用
NetworkManager.makeRequest("https://api.example.com")

替代Java静态方法的最佳实践,初始化时机在首次访问时(线程安全)

四、伴生对象:静态成员的替代方案

kotlin 复制代码
class DatabaseClient {
    companion object {
        const val VERSION = "1.2.3"
        
        fun create(): DatabaseClient = DatabaseClient()
    }
}

// 调用
val client = DatabaseClient.create()
println(DatabaseClient.VERSION)

伴生对象成员可通过类名直接访问,支持实现接口和扩展函数

五、继承与接口:明确开放原则

kotlin 复制代码
open class Animal(val name: String) {
    open fun makeSound() = "Generic animal sound"
}

class Dog(name: String) : Animal(name) {
    override fun makeSound() = "Woof!"
}

interface Swimmer {
    fun swim() {
        println("Default swimming implementation")
    }
}

关键点:

• 类/方法默认final,需open允许继承

override强制要求显式声明重写

• 接口支持默认方法实现

六、属性访问器:精细化控制

kotlin 复制代码
class Temperature {
    var celsius = 0.0
    var fahrenheit
        get() = celsius * 9/5 + 32
        set(value) {
            celsius = (value - 32) * 5/9
        }
}

val temp = Temperature()
temp.fahrenheit = 68.0
println("${temp.celsius}°C") // 输出20.0°C

通过自定义getter/setter实现:

• 数据格式转换

• 输入有效性验证

• 延迟初始化

• 访问日志记录

七、密封类 vs 枚举类

密封类(Sealed Class)

kotlin 复制代码
sealed class Result<out T> {
    data class Success<T>(val data: T) : Result<T>()
    data class Error(val exception: Exception) : Result<Nothing>()
    object Loading : Result<Nothing>()
}

fun handleResult(result: Result<Int>) = when(result) {
    is Result.Success -> println(result.data)
    is Result.Error -> println(result.exception)
    Result.Loading -> println("Loading...")
}

优势对比枚举

  • 可携带数据(每个子类都能有独立属性)
  • 支持继承体系扩展
  • 配合when表达式实现穷尽检查

注意事项

  • 密封类是抽象的,不能直接实例化
  • 密封类的子类可以是类、对象或数据类
  • 密封类的子类必须在与密封类相同的文件中声明
相关推荐
倔强的石头10617 分钟前
【C++指南】string(三):basic_string底层原理与模拟实现详解
开发语言·c++·算法
机器鱼2 小时前
1-1 MATLAB深度极限学习机
开发语言·matlab
苏墨瀚2 小时前
C#语言的响应式设计
开发语言·后端·golang
共享家95273 小时前
链表操作:分区与回文判断
c语言·开发语言·数据结构·leetcode·链表
江沉晚呤时3 小时前
C#原型模式:通过克隆对象来优化创建过程
java·开发语言·microsoft·c#·asp.net·.netcore
苏墨瀚4 小时前
SQL语言的散点图
开发语言·后端·golang
Suwg2096 小时前
【Java导出word】使用poi-tl轻松实现Java导出数据到Word文档
java·开发语言·word·poi-tl
水w6 小时前
【pyCharm Git】根据dev分支新建dev_y分支,本地也新建dev_y分支,并将代码提交到Gitlab上的新分支dev_y上。
开发语言·git·python·pycharm·pull·push·branch
范哥来了7 小时前
python 数据可视化matplotib库安装与使用
开发语言·python·信息可视化
laimaxgg7 小时前
Qt窗口控件之颜色对话框QColorDialog
开发语言·前端·c++·qt·命令模式·qt6.3