1. 程式人生 > >Kotlin相關基礎及與Java的不同 的 筆記(仨) --拓展方法和屬性代理

Kotlin相關基礎及與Java的不同 的 筆記(仨) --拓展方法和屬性代理

感覺學習進度越來越慢了,一個新的知識點需要學習好久.

22.

Kotlin的擴充套件方法和擴充套件屬性
可以自定義方法和運算子啊
可以理解為 加強版的Utils
只需要遵循
fun X.Y():Z{}
X為類名
Y為自定義的擴充套件方法名稱,可以進行傳參
Z為擴充套件方法的返回值,如果返回值為Unit,可以省略
舉個栗子

fun main(args: Array<String>) {
    //String肯定沒有這種方法
    //拓展方法類似於工具類
    //當然在Kotlin內還有操作符進行擴充套件
    "0123456789".typewriter()
    println("abc"
*6) } //fun X(String).Y()(typewrite()):Z{}(因為沒有返回值,所以省略) fun String.typewriter(){ //逐字列印 var arr = this.toCharArray() var stringBuffer = StringBuffer() for (i in 0 until arr.size){ stringBuffer.append(arr[i].toString()) println(stringBuffer.toString()) } } //和上面的一樣,只不過是有引數和返回值
operator fun String.times(int:Int):String{ var sb = StringBuffer() for (i in 0 until int){ sb.append(this) } return sb.toString() }

都是String新增擴充套件方法,第一個是普通的擴充套件方法,第二個是 操作符擴充套件方法

擴充套件屬性的話,沒什麼意義,其實就是setter/getter

var String.a:String
    set(value) {
    }
    get() = "abc"

val String
.b:String get()="aaa" fun main(args: Array<String>) { "aaa".a = "111" "aaa".a "bbb".b }

只想說一句,我次奧,居然還有這種操作.
Java呼叫
原本以為又是添加註解,沒想到居然不是
Java呼叫類似於添加了註解的靜態方法,直接類名點方法名即可.
其中第一個引數receiver及對應的X的值.也就是Kotlin裡面寫的擴充套件方法的this

public static void main(String[] args) {
        Test3Kt.times("abc",4);
        Test3Kt.typewriter("0123456789");
    }

23.

Kotlin的屬性代理
話說,之前有記錄Kotlin的懶載入

val x by lazy {
    "hello"
}

比如這樣,只有當變數x在使用的時候才進行載入,賦值為”hello”.
其中lazy就是代理
點下那個by,發現跳轉的方法是:

@kotlin.internal.InlineOnly
public inline operator fun <T> Lazy<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value

也就是變數x在被呼叫的是,呼叫getValue(),賦值value即”hello”
建立一個類,把這個方法拷過來,建立屬於自己的代理.
發現由於var是 讀寫許可權,不僅僅需要getValue(),同時還需要setValue()

class OK {
    private var str :String ?= null
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        println("我呼叫了OK的getValue,是通過${property.name} 呼叫的")
        return str?:""
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, str: String) {
        println("我呼叫了OK()的setValue方法,是通過${property.name}呼叫的,設定值為:$str")
        this.str = str
    }
}

class Normal {
    //val 只讀
    val read by OK()
    //var 讀寫,所以必須要實現setValue()方法
    var write by OK()
}


fun main(args: Array<String>) {
    val n = Normal()
    //輸出列印的是X().getValue()的值
    println(n.read)
    //未對write賦值,輸出打印出來的還是OK().getValue()值,即""
    println(n.write)
    //進行賦值,會自動呼叫OK().setValue()方法
    n.write = "kotlin"
    //這次返回的即賦值後的getValue()
    println(n.write)
}
  • 自定義代理.val只讀,只需要getValue(),var讀寫,還需要setValue().
  • 代理類,setValue()需要3個引數,需要新增一個引數進行設定
  • 建立的代理類,自定義了一個內部變數str,預設為null,在getValue()內當為null,返回”“,?:是Elvis操作符
  • 當進行賦值時,就會自動呼叫代理類的setValue()方法

這是輸出結果:

我呼叫了OK的getValue,是通過read 呼叫的

我呼叫了OK的getValue,是通過write 呼叫的

我呼叫了OK()的setValue方法,是通過write呼叫的,設定值為:kotlin
我呼叫了OK的getValue,是通過write 呼叫的
kotlin

最後列印結果,因為呼叫n.read和n.write是預設呼叫OK().getValue(),即為””
對n.write進行賦值,會自動呼叫OK().setValue()
再次呼叫n.write,這次str的值為剛剛賦的值,即kotlin