1.类构造函数
1.1 基础构造函数
class Person constructor(firstName: String) {
}
首选要清楚kotlin的默认修饰是public,所以上面的也可以简写成下面的
class Person(firstName: String) {
}
如果像把构造函数变成private
class Person private constructor(firstName: String) {
}
多个参数的构造函数
class Person private constructor(firstName: String, var b: String) {
}
给构造函数的参数指定默认值
class Person private constructor(firstName: String, var b: String = "bbbb") {
}
//调用如下
var p = Person("dave")
var p = Person("dave", "b")
1.2 第二级构造函数
只有第二级构造函数
class Child(){
constructor(c: Child, a: String = "aaa") {
}
}
当第二级构造函数和基础构造函数同时存在时,第二级构造函数必须代理基础构造函数
class Child(val a: String){
constructor(c: Child, a: String = "aaa") : this(a){//使用this代理了基础构造函数
}
}
另外需要注意,下面写法是错误的
class Child(){
constructor(val c: Child, var a: String = "aaa") {
//第二级构造函数的参数不能使用val或者var修饰
}
}
2.属性
2.1 属性定义的完整语法
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
属性必须被赋值或者使用get/set,比如几种情况
var a = "aaa"
var b = "bbb"
var c: String //因为var是可读可写属性,所以必须set/get都有
set ...
get ...
val d: String //因为val是只读属性,所以只需要get
get ...
var f = "ffff"
private set //因为f属性的set方法默认是public,显性声明private set之后,f属性的set方法就变成private了
2.2 延缓属性的初始化
因为属性必须初始化,但是有些时候有需要在特定情况下延迟它的初始化,可以使用lateinit关键字
public class MyTest {
lateinit var subject: TestSubject
@SetUp fun setup() {
subject = TestSubject()
}
@Test fun test() {
subject.method() // dereference directly
}
}
2.3 覆写属性
open class Foo {
open val x: Int get { ... }
}
class Bar1 : Foo() {
override val x: Int = ...//子类覆写了父类的属性x
}
需要注意可以用var覆写val,但是不能val覆写var
2.4 属性代理
通过by关键字
class Example {
var p: String by Delegate() //by关键字代理属性
}
class Delegate {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
return "$thisRef, thank you for delegating '${property.name}' to me!"
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("$value has been assigned to '${property.name} in $thisRef.'")
}
}
3. 反向字段和反向属性
3.1 反向字段
kotlin的类不支持字段,但是当使用自定义存储时又需要反向字段,这个时候可以用field关键字
var counter = 0 // the initializer value is written directly to the backing field
set(value) {
if (value >= 0) field = value
}
3.2 反向属性
有些场景不适合使用反向字段,可以使用反向属相
private var _table: Map<String, Int>? = null
public val table: Map<String, Int>
get() {
if (_table == null) {
_table = HashMap() // Type parameters are inferred
}
return _table ?: throw AssertionError("Set to null by another thread")
}
上面这样写,只有table被调用到了,_table才会被创建。
4. 编译时常量
使用const关键字修饰,适用于如下场景
- Top-level or member of an object
- Initialized with a value of type String or a primitive type
- No custom getter
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is deprecated"
@Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { ... }