Kotlin 4 构造,对象,修饰符,关键字,委托
注:當前文檔為Kotlin自學總結,若什么地方含義模糊不清,敬請指教,謝謝:-)。
目錄:- 構造函數(shù)- 對象- 匿名對象- 對象聲明- 對象表達式和對象聲明之間的語義差異- 修飾符- 關鍵字- 委托- 類委托- 屬性委托- 要求- 延遲性- 觀察者模式- 屬性映射- 局部委托 復制代碼構造函數(shù) - 一個主構造多個次構造,主構造函數(shù)的所有的參數(shù)都有默認值
-
主構造:(類聲明之后)
//默認類聲明 + 主構造class ClazzName public constructor{}class ClazzName public @Inject constructor(val/var params1 : type = defultValue){//constructor可省略,有注解時必須存在//public 為可見性修飾符init {//init -> 初始化代碼塊,主構造的參數(shù)可以在初始化代碼塊使用}} 復制代碼 -
次構造:委托或間接委托給主構造,需要 this 關鍵字(也可有constructor前綴)
class Person(val name: String) {//類聲明 + 主構造constructor(name: String, parent: Person) : this(name) {//次構造,相當于添加參數(shù)或重新賦值name//... ...}} 復制代碼 -
創(chuàng)建一般實例 - 沒有new 關鍵字
val invoice = Invoice()val customer = Customer("Joe Smith") //創(chuàng)建使用匿名對象,對象聲明,單例請查看Kotlin-4.md 復制代碼
對象
一般對象的創(chuàng)建方式使用構造函數(shù)傳參創(chuàng)建.
1. 匿名對象
一般匿名對象的使用
window.addMouseListener(object : MouseAdapter() {override fun mouseClicked(e: MouseEvent) {// ……} }) 復制代碼多個繼承或實現(xiàn)并且需要傳參的匿名對象
open class A(x: Int) {public open val y: Int = x }interface B {……}val ab: A = object : A(1), B {override val y = 15 } 復制代碼沒有繼承或實現(xiàn)的匿名對象創(chuàng)建
fun foo() {val adHoc = object {var x: Int = 0var y: Int = 0}print(adHoc.x + adHoc.y) } 復制代碼公有函數(shù)返回值為匿名對象時,類型為Any,將不能訪問匿名對象的成員.
class C {// 私有函數(shù),所以其返回類型是匿名對象類型private fun foo() = object {val x: String = "x"}// 公有函數(shù),所以其返回類型是 Anyfun publicFoo() = object {val x: String = "x"}fun bar() {val x1 = foo().x // 沒問題val x2 = publicFoo().x // 錯誤:未能解析的引用“x”} } 復制代碼對象聲明
對象聲明只能在其他對象聲明或非內(nèi)部類中.
//有繼承的單例對象聲明 object DataProviderManager : Parent() {fun registerDataProvider(provider: DataProvider) {// ……}val allDataProviders: Collection<DataProvider>get() = // …… }//直接調(diào)用 DataProviderManager.registerDataProvider(....) 復制代碼對象表達式和對象聲明之間的語義差異
對象表達式和對象聲明之間有一個重要的語義差別:
- 對象表達式是在使用他們的地方立即執(zhí)行(及初始化)的 - 對象聲明是在第一次被訪問到時延遲初始化的 - 伴生對象的初始化是在相應的類被加載(解析)時,與 Java 靜態(tài)初始化器的語義相匹配 復制代碼修飾符
-
val和var
val 只讀;var 可變.(var默認創(chuàng)建getter,setter; val 默認創(chuàng)建 getter) 復制代碼 -
可見性修飾符
-
internal →代替→ default,意味著該成員只在相同模塊內(nèi)可見。更具體地說, 一個模塊是編譯在一起的一套 Kotlin 文件:
一個 IntelliJ IDEA 模塊;一個 Maven 或者 Gradle 項目;一次 <kotlinc> Ant 任務執(zhí)行所編譯的一套文件。 復制代碼 -
局部變量、函數(shù)和類不能有可見性修飾符。
關鍵字
-
this
-
在類的成員中,this 指的是該類的當前對象.
-
在擴展函數(shù)或者帶接收者的函數(shù)字面值中, this 表示在"."左側傳遞的接收者參數(shù)。
class A { // 隱式標簽 @Ainner class B { // 隱式標簽 @Bfun Int.foo() { // 隱式標簽 @fooval a = this@A // A 的 thisval b = this@B // B 的 thisval c = this // foo() 的接收者,一個 Intval c1 = this@foo // foo() 的接收者,一個 Intval funLit = lambda@ fun String.() {val d = this // funLit 的接收者}val funLit2 = { s: String ->// foo() 的接收者,因為它包含的 lambda 表達式// 沒有任何接收者val d1 = this}}}} 復制代碼
-
-
abstract 抽象
-
companion → static(不存在此關鍵字) 伴生對象
-
類沒有靜態(tài)方法。在大多數(shù)情況下,它建議簡單地使用包級函數(shù)。
-
需要訪問其他類內(nèi)部的函數(shù),可以把它寫成該類內(nèi)對象聲明中的一員。
class MyClass {companion object Factory { //Factory名稱可以省略fun create(): MyClass = MyClass()}}//其他類中調(diào)用需要val instance = MyClass.create()//名稱省略后val x = MyClass.Companion 復制代碼
-
-
const 編譯時常量
請查看Kotlin-3.md 編譯時常量內(nèi)容 復制代碼 -
lateinit 延遲初始化屬性使用
-
使用字段可以避免編譯時空檢查
-
只能與var配合使用
-
屬性類型不能為空或原生類型
-
可以在單元測試的@setUp函數(shù)中初始化;
-
初始化前訪問屬性會拋出"被訪問且沒有初始化"的異常.
public class MyTest {lateinit var subject: TestSubject@SetUp fun setup() {subject = TestSubject()}@Test fun test() {subject.method() // 直接解引用}} 復制代碼
-
委托
類委托
格式:
class A{fun aa()fun bb()... }class A1:A{override fun aa(){...}override fun bb(){...}... }class ClazzName(a:A):A by a{... }//使用 clazzName(A1()).aa() 復制代碼某個類通過關鍵字by,使用委托參數(shù)的方式、繼承的格式,調(diào)用自身沒有但該參數(shù)所在類標注的基類存在的所有公有函數(shù)的形式,叫做類委托.
原理:by 語句會將對應的委托對象進行內(nèi)部存儲,編譯器將生成轉發(fā)給該對象的所有標注基類的方法。
interface Base {fun print() }class BaseImpl(val x: Int) : Base {override fun print() { print(x) } }class Derived(b: Base) : Base by b //Base為BaseImpl b的基類fun main(args: Array<String>) {val b = BaseImpl(10)Derived(b).print() // 輸出 10 } 復制代碼委托屬性
使用**by關鍵字,將屬性的getter、setter委托給函數(shù)或某個類的operator** 函數(shù),
屬性委托要求
對于一個只讀屬性(即 val 聲明的),委托必須提供一個名為 getValue 的函數(shù),該函數(shù)接受以下參數(shù):
thisRef —— 必須與 屬性所有者 類型(對于擴展屬性——指被擴展的類型)相同或者是它的超類型, property —— 必須是類型 KProperty<*> 或其超類型, 這個函數(shù)必須返回與屬性相同的類型(或其子類型)。
對于一個可變屬性(即 var 聲明的),委托必須額外提供一個名為 setValue 的函數(shù),該函數(shù)接受以下參數(shù):
thisRef —— 同 getValue(), property —— 同 getValue(), new value —— 必須和屬性同類型或者是它的超類型。 getValue() 或/和 setValue() 函數(shù)可以通過委托類的成員函數(shù)提供或者由擴展函數(shù)提供。 當你需要委托屬性到原本未提供的這些函數(shù)的對象時后者會更便利。 兩函數(shù)都需要用 operator 關鍵字來進行標記。
委托類可以實現(xiàn)包含所需 operator 方法的 ReadOnlyProperty 或 ReadWriteProperty 接口之一。 這倆接口是在 Kotlin 標準庫中聲明的:
interface ReadOnlyProperty<in R, out T> {operator fun getValue(thisRef: R, property: KProperty<*>): T }interface ReadWriteProperty<in R, T> {operator fun getValue(thisRef: R, property: KProperty<*>): Toperator fun setValue(thisRef: R, property: KProperty<*>, value: T) } 復制代碼延遲性
延遲: (lazy() 是接受一個 lambda 并返回一個 Lazy 實例的函數(shù),返回的實例可以作為實現(xiàn)延遲屬性的委托.)第一次調(diào)用 get() 會執(zhí)行已傳遞給 lazy() 的 lamda 表達式并記錄結果, 后續(xù)調(diào)用 get() 只是返回記錄的結果。
延遲是具有同步鎖線程安全的,默認 LazyThreadSafetyMode.PUBLICATION傳入lazy(),使用 LazyThreadSafetyMode.NONE 模式, 它不會有任何線程安全的保證和相關的開銷。
val lazyValue: String by lazy {println("computed!")"Hello" }fun main(args: Array<String>) {println(lazyValue)println(lazyValue) } //輸出內(nèi)容 //computed! //Hello //Hello 復制代碼委托的觀察者模式
Delegates.observable()和Delegates.vetoable()
Delegates.observable() 接受兩個參數(shù):初始值和修改時處理程序(handler)。 每當我們給屬性賦值時會調(diào)用該處理程序(在賦值后執(zhí)行)。它有三個 參數(shù):被賦值的屬性、舊值和新值;
import kotlin.properties.Delegatesclass User {var name: String by Delegates.observable("<no name>") {//初始值prop, old, new -> //被賦值的屬性、舊值和新值println("$old -> $new")} }fun main(args: Array<String>) {val user = User()user.name = "first"user.name = "second" }//打印內(nèi)容為 //<no name> -> first //first -> second 復制代碼Delegates.vetoable()可以截獲一個賦值并“否決”它,在屬性被賦新值生效之前會調(diào)用傳遞給 vetoable 的處理程序。
屬性存儲到映射 - 在一個映射(map)里存儲屬性的值。
class User(val map: Map<String, Any?>) {val name: String by mapval age: Int by map }val user = User(mapOf("name" to "John Doe","age" to 25 ))println(user.name) // Prints "John Doe" println(user.age) // Prints 25 復制代碼val -> Map, var -> MutableMap
局部委托點擊此處
本文參考自 Kotlin語言中心站
轉載于:https://juejin.im/post/5a32177e6fb9a0450167f9f5
總結
以上是生活随笔為你收集整理的Kotlin 4 构造,对象,修饰符,关键字,委托的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用nginx代理跨域,使用nginx代
- 下一篇: 【下一代核心技术DevOps】:(三)私