目录
类
类的声明与实例化(没有new)
// 声明类
class User(userName: String, age: Int){
// to do
}
// 实例化
var user = User("ABC" , 123)
构造函数
Kotlin的构造函数有两种:主构造函数和次构造函数
class Person {
var name: String = ""
var age: Int = 0
// 主构造函数
constructor(name: String, age: Int) {
this.name = name
this.age = age
}
// 次构造函数,调用主构造函数
constructor(name: String) : this(name, 0)
}
- 主构造函数(重要):有且只有一个,关键词init可以声明一个局部作用域,所有init block都会被编译为主构造函数的一部分,然后按照声明顺序执行。
- 次构造函数:可以有多个,通过this调主构造函数
详情可以看这篇:Kotlin入门语法(类使用)_kotlin 类的使用
关于主构造函数,有显式和隐式
class Person(val age: Int, val name: String) {
// 类体
}
这里省略了constructor关键字,val age: Int
和 val name: String
是主构造函数的参数。在这种情况下,类体(即类中的方法和属性)直接放在类名后面。
class Person {
val age: Int
val name: String
constructor(age: Int, name: String) {
this.age = age
this.name = name
}
// 类体
}
在这种方式中,类体包含了类的属性和方法,而主构造函数的参数则通过构造函数进行初始化。
效果一个,但前者更简洁
属性
kotlin中类的属性必须被初始化,可以设置默认值或者使用lateinit
内部类
class User {
var age: Int = 0
inner class UserName {
}
}
var userName: User.UserName = User().UserName()
继承和重写
在Kotlin中,类的继承通过使用冒号 :
后跟父类类型来实现。Kotlin中的类默认是不可继承的(final),如果要允许继承,需要将类声明为open
。
open | 修饰类名、类成员名,允许子类进行重写 |
final | 修饰类名、类成员名,禁止子类进行重写 |
// 父类
open class Animal(val name: String) {
// 成员函数
fun makeSound() {
println("Some generic sound")
}
}
// 子类继承父类
class Dog(name: String) : Animal(name) {
// 子类可以重写父类的方法
override fun makeSound() {
println("Woof! Woof!")
}
// 子类可以添加自己的方法
fun barkTwice() {
println("Bark! Bark!")
}
}
接口
kotlin的接口在java接口基础上扩充了能力,允许直接实现方法体,也允许声明属性。
接口中可以包含抽象属性和具体属性,实现类必须提供抽象属性的实现
// 定义一个接口
interface Shape {
// 抽象属性
val name: String
// 抽象方法
fun calculateArea(): Double
// 具体方法
fun description(): String {
return "This is a $name"
}
}
// 实现接口的类
class Circle(override val name: String, val radius: Double) : Shape {
// 实现抽象方法
override fun calculateArea(): Double {
return Math.PI * radius * radius
}
}
注意看对抽象属性和抽象方法的实现。
数据类
在Kotlin中,数据类(Data class)是一种专门用于存储数据的类。
相当于java bean,创建时自动生成 getter/setter
equals(other: Any?)
: 用于比较两个对象是否相等。hashCode()
: 返回对象的哈希码。toString()
: 返回对象的字符串表示形式,格式为类名后跟属性名和值。- copy(): 拷贝函数
private fun showSearchPage() {
// 只有一个变量变了
searchViewState = searchViewState.copy(visible = true)
}
此外,数据类还提供了component
方法,使得可以通过解构声明来访问数据类的属性。例如:
val person = Person("Alice", 30)
val (name, age) = person
println("Name: $name, Age: $age")
可以用数据类作为解析json的容器,不过要导入第三方的kotlinx.serialization 库
companion object
companion object
允许在数据类内部定义一些与类本身关联的方法或属性,这些方法和属性可以通过类名直接访问,而无需创建类的实例。
类似于java静态成员,可以在类级别上访问,而不需要在对象的级别上
data class User(val name: String, val age: Int) {
companion object {
fun createDefaultUser(): User {
return User("DefaultUser", 0)
}
}
}
fun main() {
// 通过类名直接调用 companion object 中的方法
val defaultUser = User.createDefaultUser()
println(defaultUser)
}
密封类
在 Kotlin 中,密封类(Sealed Class)是一种特殊的类,用于表示受限的继承结构。
密封类的子类必须定义在密封类自身或同一个文件中,这样就限制了可能的子类,并提供了更加安全的继承结构。
一些密封类的特性和规则:
- 密封类本身是抽象的,不能直接实例化。
- 所有的子类必须嵌套在密封类的声明中或者与密封类在同一文件中。
- 密封类的子类可以有状态,可以包含属性和方法。
- 密封类适用于有限集合的类层次结构,其中每个子类表示一个特定的状态或情况。
密封类的一个典型用例是在when
表达式中使用,以确保对所有可能的子类进行处理,从而提供更全面的模式匹配。
sealed class Result {
data class Success(val message: String) : Result()
data class Error(val error: String) : Result()
}
fun processResult(result: Result) {
when (result) {
is Result.Success -> {
println("Success: ${result.message}")
}
is Result.Error -> {
println("Error: ${result.error}")
}
}
}
fun main() {
val successResult = Result.Success("Operation successful")
val errorResult = Result.Error("Operation failed")
processResult(successResult)
processResult(errorResult)
}
参考博客: