interface Base {
fun printMessage()
fun printMessageLine()
}
class BaseImpl(val x: Int) : Base {
override fun printMessage() { print(x) }
override fun printMessageLine() { println(x) }
}
class Derived(b: Base) : Base by b {
override fun printMessage() { print("abc") }
}
@Test
fun test17() {
val b = BaseImpl(10)
Derived(b).printMessage()//执行自身类里覆写的方法 abc
Derived(b).printMessageLine()//执行代理类里已有的方法 10
}
需要注意的是,这种覆写的成员只能由自身访问,其代理对象是访问不到的,代理对象只能访问它自身的成员:
interface Base {
val message: String
fun print()
}
class BaseImpl(val x: Int) : Base {
override val message = "BaseImpl: x = $x"
override fun print() { println(message) }
}
class Derived(b: Base) : Base by b {
// This property is not accessed from b's implementation of `print`
override val message = "Message of Derived"
}
@Test
fun test18() {
val b = BaseImpl(10)
val derived = Derived(b)
derived.print()
println(derived.message)
}
执行结果:
BaseImpl: x = 10
Message of Derived
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.")
}
}
class Example {
var p: String by Delegate()
}
@Test
fun test19(){
val e = Example()
e.p = "aaa"
println(e.p)
}
执行结果:
aaa has been assigned to ‘p’ in com.aislli.ktdemo.KotlinTest3 Example@6f75e721.com.aislli.ktdemo.KotlinTest3 E x a m p l e @ 6 f 75 e 721. c o m . a i s l l i . k t d e m o . K o t l i n T e s t 3 Example@6f75e721, thank you for delegating ‘p’ to me!
val lazyValue: String by lazy {
println("first!")
"Hello"
}
@Test
fun test20() {
println(lazyValue)
println(lazyValue)
}
执行结果:
first!
Hello
Hello
只在第一次获取该字段的值时,会进行lazy{}里的一系列处理运算,并通过lamdba形式返回结果初始化该字段的值并存储起来,之后再获取该字段值时就不会再运算了,而是直接返回之前存储的值。
class User {
var name: String by Delegates.observable("") {
prop, old, new ->
println("$old -> $new")
}
}
fun test16() {
val user = User()
user.name = "first"
user.name = "second"
}
执行结果:
-> first
first -> second
三个参数分别代表:
prop:被赋值的属性
old:旧值
new:新值
如果要禁止修改旧值操作,可以用vetoable:
class User {
var age: Int by Delegates.vetoable(0) {
property, oldValue, newValue ->
println("${property.name}:$oldValue:$newValue")
false
}
}
@Test
fun test16() {
val user = User()
user.age = 1
user.age = 2
}
执行结果:
age:0:1
age:0:2
class User(map: Map) {
val name: String by map
val age: Int by map
}
@Test
fun test21() {
val user = User(mapOf(
"name" to "John Doe",
"age" to 25
))
println(user.name) // Prints "John Doe"
println(user.age) // Prints 25
}
用map的功能来代理JSON解析等处理中的赋值操作,例如上例中map代理相当于做了类似下面的事情:
var name: String = map["name"] as String
var age: Int = map["age"] as Int
使用代理对SharedPreferences工具类进行封装:
import android.content.Context
import android.content.SharedPreferences
import kotlin.reflect.KProperty
/**
* Created by Aislli on 2018/8/9 0009.
*/
class SP(val name: String, val default: T) {
private val sp: SharedPreferences by lazy {
App.instance.getSharedPreferences(name, Context.MODE_PRIVATE)
}
operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
return getSP(name, default)
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
putSP(name, value)
}
private fun putSP(key: String, value: T) = with(sp.edit()) {
when (value) {
is String -> putString(key, value)
is Int -> putInt(key, value)
is Long -> putLong(key, value)
is Boolean -> putBoolean(key, value)
is Float -> putFloat(key, value)
else -> throw IllegalArgumentException("Cant not save this type")
}.apply()
}
@Suppress("UNCHECKED_CAST")
private fun getSP(key: String, default: T): T = with(sp) {
val res: Any = when (default) {
is String -> getString(key, default)
is Int -> getInt(key, default)
is Long -> getLong(key, default)
is Boolean -> getBoolean(key, default)
is Float -> getFloat(key, default)
else -> throw IllegalArgumentException("Cant not get this type")
}
return res as T
}
}
App.java
class App : Application() {
companion object {
lateinit var instance: App
}
override fun onCreate() {
super.onCreate()
instance = this
}
}
使用方式:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var openType by SP("open_type",false)
toast("now the opentype is $openType")//初始值为false
rg_install.setOnCheckedChangeListener { p0, p1 ->
when (p1) {
R.id.radioButton-> openType = true//自动调用了sharedPreferences.edit().putBoolean("open_type",false)
R.id.radioButton2-> openType = false
}
toast("now the opentype is $openType")//自动调用了sharedPreferences.getBoolean("open_type",false)
}
}
}
源码