Kotlin语法(十六)-代理(Delegation)
来源:互联网 发布:alpine php 编辑:程序博客网 时间:2024/05/06 02:45
参考原文:http://kotlinlang.org/docs/reference/delegation.html
类代理(Class Delegation)
代理模式提供一种实现继承的替代方式,Kotlin原生就支持代理模块。
如下,“Derived
”继承“Base
”接口,并代理了它的全部公共方法:
interface Base { fun print()}class BaseImpl(val x: Int) : Base { override fun print() { print(x) }}class Derived(b: Base) : Base by bfun main(args: Array<String>) { val b = BaseImpl(10) Derived(b).print() // prints 10}
通过“by”关键字,将“b”实例存储到Derived对象中,编译器会生成“Base
”接口的所有方法,使用“b”的实现。
代理属性(Delegated Properties)
对于很多公用属性,尽管在每次需要的时候可以通过手动实现;更好的方式是一次实现多次使用,并放到一个库(library)。
比如,有下面类型的属性:
Ø 延迟属性(lazy properties):只有第一次访问时才会计算值。
Ø 观察属性(observable properties):当该属性发生改变时,会通知监听者。
Ø map中存储属性,不是在单独的字段中。
在Kotlin中,为了满足上面几种情况,提供了代理属性(delegated properties):
class Example { var p: String by Delegate()}
语法:val/var <property name>: <Type> by <expression>,“by”关键字后面的表达式就是代理(delegate);属性的“get()”和“set()”对应代理的“getValue()”和“setValue()”。属性代理不要去实现任何接口,但需要提供“getValue()”和“setValue()”(val属性不需要,var需要)函数。
如: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.'") }}
val e = Example()println(e.p) //Example@33a17727, thank you for delegating ‘p’ to me!
同样,当给“p”赋值时,会调用代理的“setValue()”函数;前面两个参数跟“getValue()”函数一致,第三个参数为赋的值。如:
e.p = "NEW"//打印结果://NEW has been assigned to ‘p’ in Example@33a17727.
属性代理的要求(Property Delegate Requirements)
下面总结代理属性的要求:
只读属性(read-only,使用val定义)
代理类提供“getValue”函数,参数要求:
Ø 接收者(receiver):第一个参数,必须是属性对应的类或父类型。
Ø 元数据(metadata):第二个参数,必须是“KProperty<*>”或它的父类型。
Ø 该函数,必须返回一个跟属性同类型的值。
可变属性(mutable,使用var定义)
代理类的“getValue”函数跟只读属性的一样;另外还需要提供一个“setValue”函数,参数要求:
Ø 接收者(receiver):第一个参数,同“getValue”对应的参数。
Ø 元数据(metadata):第二个参数,同“getValue”对应的参数。
Ø 新值:第三个参数,类型必须跟属性一样或其父类型。
“getValue”与“setValue”函数,可以是代理类的成员函数或扩展函数。当需要将一个对象作为一个代理属性的代理,而该类没有对应的“getValue”与“setValue”函数,通过扩展函数方式实现就非常方便。
另外两个函数需要使用“operator”关键字修饰。
标准代理(Standard Delegates)
Kotlin的标准库,通过工厂方法提供了一些有用的代理类。
Lazy
“lazy()
”函数接受Lambda表达式 并 返回“Lazy<T>”实例,它可以当做延迟属性的代理实现:当第一次属性执行“get()”(获取属性值,即使用该属性)时,会通过“lazy()”函数执行添加的Lambda表达式并记录返回值;后续再使用该属性时,直接使用记录的值。val lazyValue: String by lazy { println("computed!") "Hello"}fun main(args: Array<String>) { println(lazyValue) println(lazyValue)}//prints://computed!//Hello//Hello
默认情况,延迟属性的赋值是线程同步的:只会在一个线程中计算一次值,其他线程使用同一个值。如果初始化同步不是必须的,可以通过将“lazy()”函数的参数设置为“LazyThreadSafetyMode.PUBLICATION”,那么多个线程对其同时赋值。如果可以确保属性只会在单个线程中初始化,可以将“lazy()”设置“LazyThreadSafetyMode.NONE”模式,该模式下,不会确保线程安全及相关开销。
可观察方法(Observable)
“Delegates.observable()”,包含两个参数:初始化值和 属性值修改的回调handler;每次对属性赋值操作,都会回调该handler方法(在属性赋值后执行),该方法包含三个参数,分别为:属性对象,原值,新值。
class User { var name: String by Delegates.observable("<nomalName>") { prop, old, new -> println("$old -> $new") }}fun main(args: Array<String>) { val user = User() user.name = "first" user.name = "second"}//结果://< nomalName > -> first//first -> second
另,如果需要拦截修改属性值动作并禁止修改,可以使用“Delegates.vetoable()”,参数跟“observable()”类似,第二个回调handler需要返回一个Boolean,true表示同意修改,false表示禁止修改;该回调会在属性值修改前调用。
class User { var name: String by Delegates. vetoable ("<nomalName>") { prop, old, new -> println("want modify $old -> $new") false}}fun main(args: Array<String>) {val user = User()println(user.name)user.name = "newValue"println(user.name)}//结果://< nomalName >//want modify < nomalName > -> newValue//< nomalName >
Storing Properties in a Map
经常会在map中存储属性值,经常用于如解析JSON或其他“动态”事情。可以使用map对象作为一个代理属性的代理:class User(val map: Map<String, Any?>) { val name: String by map val age: Int by map}//val user = User(mapOf( "name" to "John Doe", "age" to 25))//println(user.name) // Prints "John Doe"println(user.age) // Prints 25注:若属性定义为“var”,需要使用“
MutableMap
”代替只读的map。- Kotlin语法(十六)-代理(Delegation)
- Kotlin-19.代理/委托类(Delegation)
- JavaScript事件代理和委托(Delegation)
- JavaScript事件代理和委托(Delegation)
- JavaScript事件代理和委托(Delegation)
- JavaScript事件代理和委托(Delegation)
- JavaScript事件代理和委托(Delegation)
- JavaScript事件代理和委托(Delegation)
- JavaScript事件代理和委托(Delegation)
- JavaScript事件代理和委托(Delegation)
- Kotlin类和对象 (十二)--- 委托(Delegation)
- [转载]Python中包装(wrapping)与代理(delegation)
- 知识库--Loader--delegation model 代理模型(47)
- 代理Delegation
- Kotlin语法(一)
- Kotlin语法(二)
- Kotlin语法(三)
- Kotlin语法(四)
- 解决“Dynamic Web Module 3.0 requires Java 1.6 or newer.”错误
- UIScrollView
- Oracle 11gR2新建空表不分配Segment
- H5 混合开发 输入法遮挡内容区域解决方法
- Ubuntu下,Android刷机命令(线刷)
- Kotlin语法(十六)-代理(Delegation)
- maven本地仓库配置
- 逐帧动画 补间动画 属性动画演示
- 关于URL编码
- 最大子序列问题的解
- Android Toast工具类
- Lesson 12 Nehe
- 今天不小心跳着看了黑镜第一季三集
- h5入门知识