Kotlin相關基礎及與Java的不同 的 筆記(仨) --拓展方法和屬性代理
阿新 • • 發佈:2019-01-01
感覺學習進度越來越慢了,一個新的知識點需要學習好久.
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