Kotlin 全面學習之路 (八) -- 屬性與欄位
阿新 • • 發佈:2018-12-10
1、 宣告屬性
在 Kotlin 中 屬性分為 可變屬性 和 只讀屬性:
- var 可變
- val 只讀
示例;
class Mike {
val name: String = "Mike"
var age: Int = 25
}
2、完整的屬性宣告
宣告一個屬性的完整語法為:
var <propertyName>[: <PropertyType>] [= <property_initializer>]
[<getter>]
[<setter>]
其中 初始器(initializer)
、getter
setter
都是可選的。
我們可以自定義訪問器,具體場景為新建一個可以判斷是否為正方形的矩形類:
class Rectangle(val height: Int, val width: Int) {
val isSquare: Boolean
get() { // 屬性的獲取函式宣告
return height == width
}
}
一個自定義 setter 的例子;
var stringRepresentation: String
get() = this.toString()
set(value) {
setDataFromString(value ) // 解析字串並賦值給其他屬性
}
如果要 改變一個訪問器的可見性或者對其註解
,那麼不需要改變其預設實現,只需要定義該屬性的訪問器而不是其實現,以下為例:
var setterVisibility: String = "abc"
private set // 此 setter 是私有的並且有預設實現
var setterWithAnnotation: Any? = null
@Inject set // 用 Inject 註解此 setter
3、Backing Field
自己對 Kotlin 中相關 Backing Field
的內容比較疑惑,單獨寫一篇部落格來記錄,具體詳見。
4、後端屬性(Backing Property)
如果你希望實現的功能無法通過這種 “隱含的後端域變數” 方案來解決, 你可以使用 後端屬性(backing property) 作為替代方案:
private var _table: Map
5、編譯期常量
在闡述 編譯期常量前,我們需要先理解 執行時常量 和 編譯期常量:
- 執行時常量是編譯時並不知道其值,真正執行的時候才獲取
- 編譯期常量是編譯時候就知道其值的常量
- kotlin中 val 並不是編譯期常量,可通過反射的方式修改值,要將其轉成編譯期常量需要加上 const 關鍵詞,可提高執行效率。
已知值的屬性可以使用 const 修飾符標記為 編譯期常量,不過這些屬性需要滿足以下要求:
- 位於頂層或者是
object
的一個成員。驗證這一條件十分容易,在一個類的屬性前新增 const 修飾符,此時你會看到錯誤資訊:const 'val' are only allowed on top level or in object
。 - 用 String 或原生型別初始化 。同樣可以在程式碼中進行驗證 。
- 沒有自定義 getter 。同樣可以在程式碼中進行驗證 。
這些屬性可以用在註解中:
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is depr
ecated"
@Deprecated(SUBSYSTEM_DEPRECATED) fun foo() { …… }
6、延遲初始化屬性與變數
一般的,屬性宣告為 非空型別
必須在建構函式中 初始化
。,但是有些情況下,我們不能在建構函式內提供一個非空初始化屬性,比如需要一個類物件,但是此類物件需要通過一系列操作才可以得到,同時你還想在類體中引用該物件是避免空檢查,那麼此時延遲初始化屬性就是必要的了。
為了實現延遲初始化屬性,我們可以使用 lateinit 修飾符來標記該物件(屬性)。
public class People{
lateinit var dog: Dog()
fun setDog(dog: Dog){
this.dog = dog
}
fun showDogInfo(){
//dog?.show()
//dog!!.show()
// 此時就不用做空檢查,以上兩行程式碼就沒有必要了
dog.show()
}
}
在初始化前訪問一個 lateinit 屬性會丟擲一個特定異常,該異常明確標識該屬 性被訪問及它沒有初始化的事實。
7、覆蓋屬性
子類覆蓋父類的相應屬性使用 override
修飾符修飾該屬性。
- var 屬性可以覆蓋 val 屬性,反之不行
- 每個宣告的屬性可以由具有初始化器的屬性或者具有 getter 方法的屬性覆蓋。
8、委託屬性
自己對 Kotlin 中相關委託的內容比較疑惑,單獨寫一篇部落格來記錄,具體詳見。