数据类

简单点说:使用data class关键字,声明一个数据类,该类会帮你自动重写toString(),equal(),HashCode()方法。
通常来说,数据类的属性都是val的,即不可改变。因为通常创建数据类用于持续化数据维持,或者作为HashMap的一个键使用。而改变数据类的属性都会导致他本身失去意义。因此,kotlin为你提供了一个方法可以copy()本身。同时也可以修改某些属性值。

类委托

使用by关键字。
一个类的方法不在该类中定义,而是直接委托给另一个对象来处理。

修饰器模式

这种模式的本质就是创建一个新类,实现与原始类一样的接口并将原来的类的实例作为一个字段保存。与原始类拥有同样行为的方法不用被修改,只需要直接转发到原始类的实例。
简单点说就是给原始类套了一层壳,然后所有的接口的法方法直接转交给原始类去完成,只不过可以添加一些自定义的新方法,或者重写一部分的方法。
如果在java中去实现,也没有问题,只是需要重复写很多的模板代码。
而在kotlin中,他通过by关键字实现类委托。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface Child{
fun walk(){
println("我会走路")
}
}
class Student:Child{
fun call(){
println("我会叫")
}
}
//class Teacher( child: Child = Student()):Child by child
//现场创建一个类继承Child
class Teacher( child: Child = object:Child{}):Child by child
//用一个单例去实现
//当然在正常使用时。这里你可以直接传递一个参数进去,用来使用
fun main() {
Teacher().walk()
}

探究

  1. 如果这里重写了他的方法,是会将原始类的方法重写,还是只重写当前的类中的方法,于是做以下探究
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Teacher(val child: Child = object:Child{}):Child by child{
    override fun walk() {
    super.walk()
    println("干嘛")
    }
    }
    //用一个单例去实现
    fun main() {
    Teacher().walk()
    Teacher().child.walk()
    }
    结果为:
    也就是他并没有重写该类的方法,而是在底层自动将委托类的方法都模板套入了一遍。

对象委托

一个类的属性不在该类中定义,而是直接委托给另一个对象来处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Example {
// 被委托属性
var prop: String by Delegate() // 基础对象
}

// 基础类
class Delegate {
private var _realValue: String = "彭"

operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
println("getValue")
return _realValue
}

operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
println("setValue")
_realValue = value
}
}

fun main(args: Array<String>) {
val e = Example()
println(e.prop) // 最终调用 Delegate#getValue()
e.prop = "Peng" // 最终调用 Delegate#setValue()
println(e.prop) // 最终调用 Delegate#getValue()
}

输出:
getValue

setValue
getValue
Peng

基础类不需要实现任何接口,但必须提供 getValue() 方法,如果是委托可变属性,还需要提供 setValue()。在每个属性委托的实现的背后,Kotlin 编译器都会生成辅助属性并委托给它。 例如,对于属性 prop,会生成「辅助属性」 prop$delegate。 而 prop 的 getter() 和 setter() 方法只是简单地委托给辅助属性的 getValue() 和 setValue() 处理。

局部变量委托

一个局部变量不在该方法中定义,而是直接委托给另一个对象来处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fun main(args: Array<String>) {
val lazyValue: String by lazy {
println("Lazy Init Completed!")
"Hello World."
}

if (true/*someCondition*/) {
println(lazyValue) // 首次调用
println(lazyValue) // 后续调用

}
}
输出:
Lazy Init Completed!
Hello World.
Hello World.