我们经常使用的其实是继承,但是相对于继承使用委托的耦合性会更低。
使用继承则代码相对会比较简单,但是使用委托则会比较复杂
一、假设有interface Worker、class JavaProgrammer: Worker、class CShapeProgrammer: Worker三个类;然后新增一个经理类:Manager,经理的技能可能是会java也有可能是会C#也有可能两个都会。如果使用继承的话则需要创建两个经理类,代码太冗余;那么这里可以使用委托的方式,如下所示
interface Worker { fun work() fun takeVacation() } class JavaProgrammer: Worker { override fun work() = println("...write java") override fun takeVacation() = println("...code at beach") } class CShapeProgrammer: Worker { override fun work() = println("...write c#") override fun takeVacation() = println("...branch at ranch") } class Manager(val staff: Worker): Worker by staff { fun meeting() = println("meeting with ${staff.javaClass.simpleName}") override fun takeVacation() = println("of course") } val doe = Manager(CShapeProgrammer())
如上所示的委托方式,Manager通过传入的是C#还是java来确定委托的是哪个类,并且通过Worker by staff来实现委托(by关键字)
该委托很像继承通过by 实现类;来确定“继承的是哪个父类”, 同时Manager 继承可见的接口是Worker
二、如一上所述,如果经理同时委托俩该如何处理
interface Worker { fun work() fun takeVacation() fun fileTimeSheet() = println("Why? Really?") } class JavaProgrammer: Worker { override fun work() = println("...write java") override fun takeVacation() = println("...code at beach") } class CShapeProgrammer: Worker { override fun work() = println("...write c#") override fun takeVacation() = println("...branch at ranch") } interface Assistant { fun doChores() fun fileTimeSheet() = println("No escape from that") } class DepartmentAssistant: Assistant { override fun doChores() = println("route DepartmentAssistant") } class Manager(val staff: Worker, val assistant: Assistant): Worker by staff, Assistant by assistant { override fun takeVacation() = println("of course") override fun fileTimeSheet() { println("manally forwarding this....") assistant.fileTimeSheet() } } val doe = Manager(CShapeProgrammer(), DepartmentAssistant())
如上所示,Worker和Assistant同时存在接口fileTimeSheet,此时必须要重写该函数否则会出现冲突的情况
因为代理也算是继承,所以如上的doe可以有如下的赋值
val worker: Worker = doe val assistant: Assistant = doe worker.work() //No escape from that worker.fileTimeSheet() //route DepartmentAssistant assistant.doChores() //manally forwarding this.... assistant.fileTimeSheet()//No escape from that
如上可以看到,worker或者是assistant都是属于Manager类,他们调用的接口显示上跟多态是一致的
三、关于设值的委托
如果相对参数的设值底层进行特殊处理,则可以使用设值委托
import kotlin.reflect.KProperty class PoliteString(var content: String) { operator fun getValue(thisRef: Any?, property: KProperty<*>) = content.replace("stupid", "sXXXXdddddX") operator fun setValue(thisRef: Any, property: KProperty<*>, value: String) { content = value } } var comment: String by PoliteString("some nice message") // 这里String使用PoliteString进行委托 println(comment) //some nice message comment = "this is stupid" println(comment) //this is sXXXXdddddX 这里将stuipid过滤 println(comment.length) //19 这里使用过滤后的值进行计算长度 fun beingpolite(content: String) = PoliteString(content) var comment1: String by beingpolite("kkqqq stupid") println(comment1)
四、关于懒操作
为了程序的顺序操作,可能某些参数计算了但是因为if等原因导致该参数最后没有被用到;如果说没被用到就不进行对该参数的计算,那么会大大节省很多时间
fun getTemperature(city: String): Double { println("fetch from webservice for $city") return 30.0 } val showTemperature = false val city = "Boulder" val temperature by lazy {getTemperature(city)} if (showTemperature && temperature > 20) println("Warm") else println("nothing to")
如上,当showTemperature为false的时候,不需要计算temperature的值;这里使用了by lazy的方式,后面接一个lambda表达式,当确实要用到该参数的时候再调用该lambda表达式
五关于属性值变化的监听
1、当值变化的时候想要做一些额外的操作,则可以用observable的代理
var count by observable(0) { property, oldValue, newValue -> println("Property: $property old: $oldValue, new: $newValue") } println("The new value count = $count") ++count println("The new value count = $count") ++count println("The new value count = $count")
如上的输出如下所示:
The new value count = 0
Property: var Observe.count: kotlin.Int old: 0, new: 1
The new value count = 1
Property: var Observe.count: kotlin.Int old: 1, new: 2
The new value count = 2
如上所示,每一个的值的变更都会调用该observable对应的lambda表达式
2、当拒绝某个参数的赋值时候,可以使用如下
var max by vetoable(0) { property, oldValue, newValue -> oldValue < newValue } println("The new value max = $max") max = 10 println("The new value max = $max") max = 4 println("The new value max = $max")
如下的输出:
The new value max = 0
The new value max = 10
The new value max = 10
当最后一次赋值为4的时候,因为vetoable返回了false则拒绝赋值
标签:count,委托,kotlin,Worker,value,fun,println,new From: https://www.cnblogs.com/czwlinux/p/16875694.html