首页 > 其他分享 >kotlin 委托

kotlin 委托

时间:2022-11-10 00:22:44浏览次数:38  
标签:count 委托 kotlin Worker value fun println new

我们经常使用的其实是继承,但是相对于继承使用委托的耦合性会更低。

使用继承则代码相对会比较简单,但是使用委托则会比较复杂

一、假设有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

相关文章

  • JvmMultifile 注解在 Kotlin 中的应用
    接触过Kotlin之后,我们会利用其扩展方法特性创建很多便捷的方法来实现更好更快的编码。比如我们对于RxJava进行一些简单的扩展方法实现。下面的这段代码实现一个将任意的对象......
  • JvmName 注解在 Kotlin 中的应用
    JvmName注解是Kotlin提供的一个可以变更编译器输出的注解,这里简单的介绍一下其使用规则。应用在文件上未应用@JvmNamepackagecom.example.jvmannotationsampleimportand......
  • 用JavaScript实现按钮的事件委托并且区分按钮
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content......
  • C# 委托
    委托初始委托是一个引用类型,其实是一个类(当成类来看待),保存的是方法的指针,当我们调用委托的时候这个方法就立即被执行。委托的关键字:delegate创建委托://定义委托deleg......
  • 用JavaScript实现事件移除,派发,委托
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content......
  • kotlin中ViewModel + ViewBinding使用实例
    android使用androidx后可以使用viewbinding了,因为是内生库,也蛮好用的。butterknife感觉已经在退环境了。文章列出ViewModel+ViewBinding,是MVVM模式的简单使用,没有涉及......
  • 事件委托和排他思想
    一、事件委派1.理解DOM事件流事件流描述的是从页面中接收事件的顺序。事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。DOM事件流分为三个......
  • kotlin用于注解处理kapt配置
    使用场景:为了使用 @AutoService(xx::class)AndroidStudio版本:AndroidStudioBumbleBee2021.1.1Patch3build.gradle(Project)载入插件:plugins{...id"o......
  • 【IoT】产品认证:国密认证中的委托人、生产者、生产企业是什么意思?
    委托人:就是证书的持有人。生产者:原来叫制造商,对产品质量进行控制,并对产品销售负责。生产企业:产品的加工工厂。举例:A公司开发了一款产品,这款产品由B公司代工生产,C公司拿到这......
  • delegate 委托
    委托delegate关键词event关键字,添加后将委托封装成事件。事件和委托区别:事件相对于委托来说更加安全。四种类型委托//自定义无参无返回值publicdelegatevoidActi......