1. Agent mode
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()//Execute method abc overridden in its own class
Derived(b).printMessageLine()//Execution Agent Class Execution Method 10
}
It is important to note that members of this override can only be accessed by themselves, that their proxy objects cannot be accessed, and that proxy objects can only access their own members:
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)
}
Execution results:
BaseImpl: x = 10
Message of Derived
2. Attribute Delegation
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)
}
Execution results:
aaa has been assigned to 'p' in com.aislli.ktdemo.KotlinTest3Example@6f75e721.com.aislli.ktdemo.KotlinTest3Example@6f75e721.com.aislli.ktdemo.KotlinTest3Example@6f75e721, thank you for delegating 'p' to me!
3. kotlin provides several common standard proxy methods
3.1 lazy
val lazyValue: String by lazy {
println("first!")
"Hello"
}
@Test
fun test20() {
println(lazyValue)
println(lazyValue)
}
Execution results:
first!
Hello
Hello
Only the first time you get the value of the field, a series of processing operations in lazy {} are performed, and the result is returned as lamdba to initialize the value of the field and store it. When you get the value of the field again, the operation is no longer performed and the previously stored value is returned directly.
3.2 observable
class User { var name: String by Delegates.observable("<no name>") { prop, old, new -> println("$old -> $new") } } fun test16() { val user = User() user.name = "first" user.name = "second" }
Execution results:
-> first
first -> second
The three parameters represent:
prop: assigned attribute
Old: old value
New: new value
If you want to prohibit modifying old values, you can use 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
}
Execution results:
age:0:1
age:0:2
3.3 map
class User(map: Map<String, Any?>) {
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
}
Use the map's capabilities to proxy assignments in processes such as JSON parsing, for example, the map proxy in the example above does something similar to the following:
var name: String = map["name"] as String
var age: Int = map["age"] as Int