Kotlin的语法入门-类

前言

类的形式

普通类

1
2
3
4
5
class ResultVo<T> {
var code: Int = 0
var msg: String = ""
var obj: T? = null
}

数据类(pojo)

1
data class Customer(val name: String, val email: String)

自动添加的方法:

  • 为所有属性添加 getters ,如果为 var 类型同时添加 setters
  • equals()
  • haseCode()
  • toString()
  • copy()

限制

data class 有一些特殊限制:

  • 主构造函数至少需要一个参数
  • 主构造函数的参数必须是 valvar(不能是无修饰符的参数)
  • 不能是抽象类、密封类、内部类或枚举类

数据类以及解构声明

组件函数允许数据类在解构声明中使用:

1
2
3
val jane = User("Jane", 35)
val (name, age) = jane
println("$name, $age years of age") // prints "Jane, 35 years of age"

枚举

1
2
3
4
5
enum class Color(val rgb: Int) {
RED(0xFF0000),
GREEN(0x00FF00),
BLUE(0x0000FF)
}

密封类

密封类(Sealed Class)是一种特殊的类,用于表示受限的类层次结构,它的子类是固定的,不能在定义密封类的文件外部添加新的子类。

这种特性使得密封类非常适合用于表示固定的状态集合或结果类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 密封类定义所有可能的请求状态
sealed class NetworkResult<out T> {
// 加载中状态(无数据)
object Loading : NetworkResult<Nothing>()

// 成功状态(携带数据)
data class Success<out T>(val data: T) : NetworkResult<T>()

// 失败状态(携带错误信息)
data class Error(
val message: String,
val exception: Exception? = null
) : NetworkResult<Nothing>()
}

// 使用密封类处理请求结果
fun handleResult(result: NetworkResult<Int>) {
// when 语句会强制检查所有子类,避免遗漏
when (result) {
is NetworkResult.Loading -> println("正在加载...")
is NetworkResult.Success -> println("请求成功,数据:${result.data}")
is NetworkResult.Error -> println("请求失败:${result.message}")
}
}

fun main() {
val loading = NetworkResult.Loading
val success = NetworkResult.Success(200)
val error = NetworkResult.Error("网络超时")

handleResult(loading) // 输出:正在加载...
handleResult(success) // 输出:请求成功,数据:200
handleResult(error) // 输出:请求失败:网络超时
}

与其他类型的对比

类型 特点 适用场景
密封类 子类固定,可携带数据,灵活 复杂状态管理(如 UI 状态、请求结果)
枚举(enum) 实例固定,不可携带动态数据 简单的标签式状态(如颜色、类型)
普通类 可自由继承,无限制 需要灵活扩展的类层次结构

可见修饰符

  • private:同一类或文件(针对包级别定义)中可见
  • protected:同private 加子类可见
  • internal:在同一个模块中可见(如果声明范围的所有者是可见的)
  • public:公共,所有都可见

单例

1
2
3
4
5
object MyClass{
fun aa(){

}
}

那么MyClass.aa()其实就是调用单例的aa方法

继承

open 关键字用于声明一个可以被继承或者被子类重写的类、方法或者属性。

Kotlin 中的类、方法、属性默认是不可继承或重写的,如果你希望某个类可以被其他类继承,或者某个方法或属性可以在子类中被重新实现,就需要使用 open 关键字来进行声明。

自定义组件

1
2
3
4
5
6
7
8
9
10
open class SpliterLinearLayout : LinearLayoutCompat {

constructor(context: Context) : super(context) {

}

constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {

}
}

类扩展

1
2
3
4
5
fun <T> MutableList<T>.swap(x: Int, y: Int) {
val tmp = this[x] // 'this' corresponds to the list
this[x] = this[y]
this[y] = tmp
}

调用方式

1
2
val list = mutableListOf(1, 2, 3)
list.swap(0, 2)// 在 `swap()` 函数中 `this` 持有的值是 `list`

扩展是被静态解析

延迟初始化

在 Kotlin 中,lateinit 关键字用于延迟初始化属性,即在声明属性时不需要立即赋初始值,而是在后续的某个时间点再进行赋值。

lateinit 只能用于非空类型的属性,并且必须是类属性(不能是局部变量)。

下面是一个简单的示例,演示了如何在 Kotlin 中使用 lateinit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Example {
lateinit var name: String

fun init() {
name = "WeTab"
}

fun printName() {
// 在确保 name 已经被初始化之后才能访问它
if (::name.isInitialized) {
println(name)
} else {
println("name 未被初始化")
}
}
}

fun main() {
val example = Example()
example.init()
example.printName()
}

在这个示例中,name 属性被标记为 lateinit,在 initializeName() 方法中对其进行了初始化,然后在 printName() 方法中检查是否已经被初始化并打印其值。

需要注意的是,如果在访问一个未被初始化的 lateinit 属性时,会抛出 UninitializedPropertyAccessException 异常,因此在访问之前必顋确保已经对其进行了初始化。

类对比

Java

1
2
3
Intent t = new Intent();
t.setClass(this,LoginActivity.class);
startActivity(t);

Kotlin

1
2
3
val t = Intent()
t.setClass(this, LoginActivity::class.java)
startActivity(t)

接口写法对比

Java

1
2
3
4
5
6
7
8
9
10
11
12
13
OkGo.<TUserBean>post("")
.params("","")
.execute(new JsonCallback<TUserBean>() {
@Override
public void onSuccess(Response<TUserBean> response) {

}

@Override
public void onFinish() {
super.onFinish();
}
});

Kotlin

1
2
3
4
5
6
7
8
9
10
11
OkGo.post<TUserBean>("")
.params("", "")
.execute(object : JsonCallback<TUserBean>() {
override fun onSuccess(response: Response<TUserBean>) {

}

override fun onFinish() {
super.onFinish()
}
})

静态属性和方法

Kotlin中定义

1
2
3
4
5
6
7
8
9
class ApiModel {
companion object {
val baseUrl = "http://www.psvmc.cn"

fun getName(): String {
return "小明"
}
}
}

Kotlin中调用

1
2
ApiModel.baseUrl
ApiModel.getName()

Java中调用

1
2
ApiModel.Companion.getBaseUrl();
ApiModel.Companion.getName();

所以建议静态属性和方法建议还用Java来写

类转换

1
activity as ClassActivity