目录
在看下面之前,先要知道几个概念
- Java的类和方法默认都是open的,而Kotlin默认的都是final的,所以要想在kotlin中定义一个可以重写的类或者方法,记得添加open。
- 因为接口设置的方法都是待重写的属性和方法,所以默认都是open的
- 抽象类可以理解成一半类,一半接口,只要你声明了abstrat,就说明它希望被覆盖,所以声明了abstrat的属性和方法是默认open的。
- 只要你重写了一个方法或属性,也就是它们用override修饰了,就一定是open的,可能需要你用final进行限制
1. 类
构造方法
每个类构造方法有一个主构造器和多个次构造器组成。主构造器要写到类声明那一行中,参数可以定义成var或者val,可以初始化,而且其他初始代码块要用init来包裹。
class Person constructor(var firstName: String = "") {
init {
println("FirstName is $firstName")
}
}
次构造方法一定要加前缀consructor,引入主构造函数,因为主构造函数是创建代码主要途径,次构造方法只能在主构造函数的基础上添加功能。
class Person(val name: String) {
constructor (name: String, age:Int) : this(name) {
// 初始化...
}
}
属性
var声明可变的属性,默认实现gettter和setter。val声明不可变属性,默认实现getter,不能写setter。
调用直接用对象.属性名就可以,实际上就是在调用他的getter和setter方法。getter权限跟字段一样,setter可以跟字段不一致。
class Person {
var lastName: String = "zhang"
get() = field.toUpperCase() // 将变量赋值后转换为大写
private set
}
field后备字段
不使用后备字段而是使用类字段,实际上相当于调用这个类字段的getter和setter方法
class People {
var name: String
get() = name
set(value) {
name = value
}
}
// 相当于setter和getter都递归调用了
public final class People {
@NotNull
public final String getName() {
return this.getName();
}
public final void setName(@NotNull String value) {
Intrinsics.checkParameterIsNotNull(value, "value");
this.setName(value);
}
}
// 所以我们要用后备字段,后备字段仅仅用于getter和setter中
class People {
var name: String = "Mike"
get() = field
set(value) {
field = value
}
}
2. 接口
接口的属性要么是抽象的,要么要提供访问器的实现,不能出现后备字段。
实现接口的类只需要定义自己缺少的实现
interface Named {
val name: String
}
interface Person : Named {
val firstName: String
val lastName: String
override val name: String get() = "$firstName $lastName"
}
data class Employee(
// 不必实现“name”
override val firstName: String,
override val lastName: String,
val position: Position
) : Person