Kotlin是现在我们做新版本的Android项目首选的开发语言,其中的 data class 相较于其他编程语言有所不同,深刻理解对于我们提高开发原生App的效率有很大的帮助。
1. 基本概念
data class
是 Kotlin 中一种特殊的类,主要用于存储数据。编译器会自动为 data class
生成一些常用的函数,减少样板代码。
1
| data class PhotoTaken(val photoInfo: String, val photo_filename: String) : Event()
|
2. 自动生成的函数
当声明一个 data class
时,Kotlin 编译器会自动生成以下函数:
基础函数
equals()
和 hashCode()
- 用于对象比较和哈希计算
toString()
- 返回包含所有属性的字符串表示
copy()
- 创建对象副本
componentN()
函数 - 支持解构声明
示例演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| data class Person(val name: String, val age: Int)
val person1 = Person("张三", 25) val person2 = Person("张三", 25) val person3 = Person("李四", 30)
println(person1 == person2) println(person1.hashCode() == person2.hashCode())
println(person1.toString())
val person4 = person1.copy(age = 26) println(person4)
val (name, age) = person1 println("姓名: $name, 年龄: $age")
|
同时,也可以通过data class的属性直接访问其值:
1 2
| println(person1.name) println(person1.age)
|
更详细的举例说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| data class Person(val name: String, val age: Int, var address: String)
val person = Person("张三", 25, "北京市")
println(person.name) println(person.age)
println(person.address) person.address = "上海市" println(person.address)
|
3. 主要特性
主构造函数要求
data class
必须至少有一个主构造函数参数:
1 2 3 4 5
| data class User(val id: Int, val name: String)
data class EmptyDataClass // 编译错误
|
属性可变性
支持 val
(只读)和 var
(可变)属性:
1 2 3 4 5
| data class MutableUser(var id: Int, val name: String)
val user = MutableUser(1, "张三") user.id = 2
|
4. 实际应用场景
1. 数据传输对象 (DTO)
1 2 3 4 5 6
| data class UserDto( val id: Long, val username: String, val email: String, val createdAt: String )
|
2. 网络请求响应
1 2 3 4 5
| data class ApiResponse<T>( val code: Int, val message: String, val data: T? )
|
3. 状态管理
1 2 3 4 5
| sealed class Event { data class PhotoTaken(val photoInfo: String, val photo_filename: String) : Event() data class LogMessage(val message: String) : Event() }
|
4. 配置信息
1 2 3 4 5
| data class AppConfig( val apiUrl: String, val timeout: Int, val retryCount: Int )
|
5. 高级用法
copy() 函数的使用
1 2 3 4 5
| data class Product(val id: Int, val name: String, val price: Double, val category: String)
val product = Product(1, "手机", 2999.0, "电子产品") val discountedProduct = product.copy(price = 2499.0) val renamedProduct = product.copy(name = "智能手机", category = "智能设备")
|
解构声明
1 2 3 4 5 6 7 8 9 10 11
| data class Point(val x: Int, val y: Int)
val point = Point(10, 20) val (x, y) = point println("坐标: ($x, $y)")
val points = listOf(Point(1, 2), Point(3, 4), Point(5, 6)) for ((x, y) in points) { println("点: ($x, $y)") }
|
与集合操作结合
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| data class Student(val name: String, val score: Int)
val students = listOf( Student("张三", 85), Student("李四", 92), Student("王五", 78) )
val highScorers = students.filter { it.score > 80 } val names = students.map { it.name }
val groupedByScore = students.groupBy { if (it.score >= 90) "优秀" else "一般" }
|
6. 注意事项和限制
1. 继承限制
1 2 3 4 5 6
| open class BaseEntity(val id: Long) data class User(override val id: Long, val name: String) : BaseEntity(id)
|
2. 与密封类结合
1 2 3 4
| sealed class Result<T> { data class Success<T>(val data: T) : Result<T>() data class Error<T>(val message: String) : Result<T>() }
|
3. 注意重写函数
如果手动重写了自动生成的函数,编译器不会重新生成:
1 2 3 4 5
| data class CustomToString(val name: String, val age: Int) { override fun toString(): String { return "Custom: $name ($age years old)" } }
|
7. 在您的项目中的应用
在我写的一个测试项目的 [UiHandler.kt] (代码在我的github或者gitee上)(file:///Users/test003/AndroidStudioProjects/testWifi001/app/src/main/java/com/example/testwifi001/UiHandler.kt) 中,data class
的使用体现了以下优势:
- 类型安全:每个事件类型都有明确的参数定义
- 简洁性:避免手动编写 getter、equals 等方法
- 可读性:一眼就能看出事件携带的数据
- 解构支持:可以在接收端方便地解构使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| data class PhotoTaken(val photoInfo: String, val photo_filename: String) : Event()
UiHandler.sendEvent(UiHandler.Event.PhotoTaken(photoInfo, filePath))
override fun onUiEvent(event: UiHandler.Event) { when (event) { is UiHandler.Event.PhotoTaken -> { handlePhotoTaken(event.photoInfo, event.photo_filename) } } }
|
这种设计模式在 Android 开发中非常常见,特别是在事件总线、状态管理、网络响应等场景中广泛使用。