Delegation pattern is a basic skill in software design pattern. In delegate mode, two objects participate in processing the same request, and the objectthat accepts the request delegates the request to another object to process.
The delegate of a class, that is, a method defined in one class is actually implemented by calling the method of an object of another class. The derived class in the following example In Attribute delegation means that the attribute value of a class is not defined directly in the class, but entrusted to a proxy class, so as to realize the unified management of the attributes of this class. Attribute delegate syntax format: Attribute name: attribute name Type: data type of the attribute Expressions: delegated agent class This class needs to contain The output is as follows: A number of factory methods have been built into the standard Execute the output result: The handler that executes the event after the attribute assignment, which has three parameters: the assigned attribute, the old value, and the new value: Execute the output result: A common use case is to store the value of an attribute in a map. This oftenoccurs in applications like parsing JSON or doing other “dynamic” things.In this case, you can use the mapping instance itself as a delegate to implement the delegate property. Execute the output result: If you use the Execute the output result: It is important to note that an exception is thrown if the property is accessed before the assignment. You can declare local variables as delegate properties. For example, you caninitialize a local variable lazily: For a read-only property (that is, the val property), its delegate must provide a file named This function must return the same type (or its subtype) as the property. For a variable value (mutable) attribute (that is, Behind the implementation of each delegate property By defining For example, if you want to check the property name before binding, you can write: Before creating Without this ability to intercept the binding between a property and its delegate, you must explicitly pass the property name in order to achieve thesame function, which is not very convenient: In the generated code, the Attention please,
最近几年来,地理信息系统无论是在理论上还是应用上都处在一个飞速发展的阶段。 GIS被应用于多个领域的建模和决策支持,如城市管理、区划、环境整治等等,地理信息成为信息时代重要的组成部分之一; “数字地球”概念的提出,更进一步推动了作为其技术支撑的GIS的发展。 与此同时,一些学者致力于相关的理论研究,如空间感知、空间数据误差、空间关系的形式化等等。 这恰好说明了地理信息系统作为应用技术和学科的两个方面,并且这两个方面构成了相互促进的发展过程。 Kotlin directly support the delegation model, more elegant and concise. Kotlin by keyword by implement the delegate. 3.18.1. Class delegation #
Derived inherited the interface Base all methods and delegate an incoming Base class to execute these methods.// Create Interface interface Base { fun print() } // The delegated class that implements this interface class BaseImpl(val x: Int) : Base { override fun print() { print(x) } } // Establishing a delegate class through the keyword by class Derived(b: Base) : Base by b fun main(args: Array<String>) { val b = BaseImpl(10) Derived(b).print() // Output 10 }
Derived statement by clause indicates that the b save in Derived and the compiler will generate the object instance inherited from the Base interface and forwards the call to the b . 3.18.2. Attribute delegation #
val/var <Attribute Name>:<Type>by<Expression>
var/val : Attribute type (variable/read-only) by keyword is the delegate, the attribute get() method (and set() method to be delegated to this object getValue() and setValue() method. Property delegates do not have to implement any interfaces, but must provide getValue() function (for var property, you also need to setValue() function). 3.18.3. Define a delegated class #
getValue() methods and setValue() method and parameters thisRef is the object of the delegated class prop is the object of the delegated property.import kotlin.reflect.KProperty // Define a class that contains attribute delegates class Example { var p: String by Delegate() } // Delegated Class class Delegate { operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return "$thisRef, Here, the ${property. name} attribute is delegated" } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { println("$The ${property.name} attribute of thisRef is assigned a value of $value") } } fun main(args: ArrayExample@433c675d Here, the p attribute is delegated Example@433c675d Assign the p attribute of to Runoob Example@433c675d Here, the p attribute is delegated
3.18.4. Standard entrustment #
Kotlin library to implement the delegate of properties. 3.18.5. Delay property Lazy #
lazy() is a function that accepts a Lambda expression as an argument, returns a Lazy get() execution has been passed to the lazy() of lamda expression and record the result, and then call get() just return the results of the record. val lazyValue: String by lazy { println("computed!") // First call output, second call not executed "Hello" } fun main(args: Array<String>) { println(lazyValue) // First execution, execute the output expression twice println(lazyValue) // The second execution only outputs the return value }
computed! Hello Hello
3.18.6. Observable attribute
Observable # observable can be used to implement the observer pattern. Delegates.observable() function takes two arguments: the first is the initialization value, and the second is the responder (handler) to the property value change event. import kotlin.properties.Delegates class User { var name: String by Delegates.observable("Initial value") { prop, old, new -> println("old value:$old -> new value:$new") } } fun main(args: Array<String>) { val user = User() user.name = "First assignment" user.name = "Second assignment" }
Old value: Initial value ->New value: First assignment Old value: First assignment ->New value: Second assignment
3.18.7. Store attributes in the mapping #
class Site(val map: Map
Novice Tutorial www.runoob.com
var property, you need to set the Map replace it with MutableMap : class Site(val map: MutableMap
Novice Tutorial www.runoob.com -------------- Google www.google.com
3.18.8. Not Null #
notNull is suitable for situations where the attribute value cannot be determined at the initialization stage. class Foo { var notNullBar: String by Delegates.notNull<String>() } foo.notNullBar = "bar" println(foo.notNullBar)
3.18.9. Local delegate attribute #
fun example(computeFoo: () -> Foo) { val memoizedFoo by lazy(computeFoo) if (someCondition && memoizedFoo.isValid()) { memoizedFoo.doSomething() } }
memoizedFoo variables are only evaluated on the first access. If someCondition if it fails, the variable will not be calculated at all. 3.18.10. Attribute delegation requirement #
getValue() function. This function accepts the following parameters:
thisRef - must be the same as the property owner type (for extended attributes - the type being extended) or its supertype property - must be a type KProperty<*> or its supertype. var property), except getValue() function, its delegate must provide another one named setValue() which accepts the following parameters:
property - must be a type KProperty<*> or its supertype. new value must be of the same type as the property or its supertype. 3.18.11. Translation rules #
Kotlin compilergenerates an auxiliary property and delegates it. For example, for attributes prop to generate hidden properties prop$delegate and the code for the accessor is simply delegated to this additional property class C { var prop: Type by MyDelegate() } // This is the corresponding code generated by the compiler: class C { private val prop$delegate = MyDelegate() var prop: Type get() = prop$delegate.getValue(this, this::prop) set(value: Type) = prop$delegate.setValue(this, this::prop, value) } Kotlin compiler provides information in the parameters about prop all the necessary information: the first parameter this reference to aninstance of the external class C and this::prop KProperty reflection object of type that describes the prop himself. 3.18.12. Provide entrustment #
provideDelegate operator, you can extend the logic of creating properties to implement the delegated object. If by objectusedon the right will provideDelegate if it is defined as a member oran extension function, the function is called to create a property delegateinstance. provideDelegate possible usage scenario is when a property is created (not just in its getter or setter check for property consistency. class ResourceLoader
provideDelegate parameters same as getValue :
thisRef - must be the same as the property owner type (for extended attributes - the type being extended) or its supertype property - must be a type KProperty<*> or its supertype. MyUI instance, call for each property provideDelegate method and immediately perform the necessary validation. // Check attribute names without using the 'provideDelegate' function class MyUI { val image by bindResource(ResourceID.image_id, "image") val text by bindResource(ResourceID.text_id, "text") } fun <T> MyUI.bindResource( id: ResourceID<T>, propertyName: String ): ReadOnlyProperty<MyUI, T> { checkProperty(this, propertyName) // Create Delegation }
provideDelegate method to initialize the auxiliary prop$delegate property. Compare for attribute declarations val prop: Type by MyDelegate() generated code is the same as above (when provideDelegate code generated when the method does not exist: class C { var prop: Type by MyDelegate() } // This code is when the "provideDelegate" function is available // Code generated by the compiler: class C { // call “provideDelegate” to create additional “delegate“ attributes private val prop$delegate = MyDelegate().provideDelegate(this, this::prop) val prop: Type get() = prop$delegate.getValue(this, this::prop) } provideDelegate method only affects the creation of auxiliary properties and does not affect the getter or setter generated code.