Kotlin基础学习---面向对象(三)

目录

一、属性代理

二、数据类


一、属性代理

什么是代理,请童鞋们自行百度~。那什么是属性代理呢?我们先看下面的例子:

//代理类
class DelegateTest{
    var v by Delegates.notNull<Any>()
    operator fun getValue(thisRef:Any?,property:KProperty<*>):Any{
        println("我是DelegateTest中的getValue")
        return v
    }
    operator fun setValue(thisRef: Any?,property: KProperty<*>,value:Any){
        println("我是DelegateTest中的setValue")
        v = value
    }
}

//测试类
class TestA{
    var value by DelegateTest()
}

fun main(args: Array<String>) {
    val ta = TestA()
    ta.value = "vvvvv"
    println("------------------")
    println("我是get方法:${ta.value}")
}

输出如下

我是DelegateTest中的setValue
------------------
我是DelegateTest中的getValue
我是get方法:vvvvv

DelegateTest类是一个实现了代理功能的类,这个类中实现了setValuegetValue的两个方法,这个方法是必要实现的。

TestA是测试类,其中的value通过by关键字实现了被代理的功能

我们在main方法中设置了TestA类中的value值,此时执行到了DelegateTest中的setValue方法,相当于DelegateTestset这个动作进行了拦截,然后做了定制的操作;随后又打印了TestA中的value值,相当于是get动作,DelegateTest中的getValue方法被执行。

代理类的setValuegetValue中可以实现业务的操作,比如属性值得存储和获取等,简化和方法了我们的操作。

Kotlin中也有很多实现了属性代理的类,供程序使用,比如上面DelegateTest中的Delegate这个类,这个类有三个api:Delegate.notNullDelegate.observableDelegate.vetoable

Delegate.notNull

这个方法很好理解,使用了Delegate.notNull的属性不能为空,但是可以先被申明出来。在Kotlin中是不能不对属性进行初始化的,而使用了Delegate.notNull属性之后,表示此属性的初始化操作可以延后来做,具体什么时候做由使用者来决定。

Delegate.observale

我们先看这个方法的使用

class Student{
    var name:String by Delegates.observable(initialValue = "Beijing",onChange = {property, oldValue, newValue ->
        println("property: ${property.name}  oldValue: $oldValue  newValue: $newValue")
    })
}

fun main(args: Array<String>){
    val student = Student()
    student.name = "Beijing"
    student.name = "Chengde"
}

输出

property: name  oldValue: Beijing  newValue: Beijing
property: name  oldValue: Beijing  newValue: Chengde

作用显而易见,使用了此方法的属性,当属性值发生改变时,就会执行observable方法中第二个参数实现的方法

Delegate.vetoable

我们先看一下使用的代码
 

class VetoableTest{
    var name:String by Delegates.vetoable(initialValue = ""){property, oldValue, newValue ->
        if(newValue=="gzc"){
            return@vetoable true
        }else{
            return@vetoable false
        }
    }
}

fun main(args: Array<String>) {
    val vetoableTest = VetoableTest()
    vetoableTest.name = "liming"
    println("name:${vetoableTest.name}")
    vetoableTest.name = "gzc"
    println("name:${vetoableTest.name}")
}

输出:

name:
name:gzc

使用了这个方法的属性,在赋值的时候先会进行比较,符合条件的话,返回true,赋值成功;不符合条件的话,返回false,赋值为默认值

二、数据类

数据类也是Kotlin中特有的类型,类被data关键字修饰的话,可以实现toStringequals/hashCodecomponentNcopy方法,就不需要我们手动的去写了

如下:

//普通类
class CommonClass(val name:String,val age:Int)
//数据类
data class DataClass(val name:String,val age:Int)

fun main(args: Array<String>) {
    val commonClass = CommonClass("gzc",27)
    println(commonClass)
    val dataClass = DataClass("liming",26)
    println(dataClass)
}

输出

CommonClass@7cc355be
DataClass(name=liming, age=26)

使用数据类的时候一定要注意,当类成为数据类的时候,这个在字节码中已经被final修饰,并且没有无参构造器,所以使用的时候你可能会遇到各种奇葩的问题,针对上述的问题,我们使用两个插件来解决:allopen和noarg,我们只需要在gradle或者maven中添加这两个插件。具体的使用,推荐博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值