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() { ... }