数据类
在Java中我们判断对象是否相等需要使用到equals
, 而在Kotlin中直接使用==
来判断对象是否相等
class User(val name:String)
fun main(args: Array<String>) {
val user1 = User("Herman")
val user2 = User("Herman")
println(user1==user2)
}
这个例子输出的结果为 false
, 熟悉Java的小伙伴都知道User对象缺少了 equals
方法,
class User(val name: String) {
override fun equals(other: Any?): Boolean {
if (Objects.isNull(other) || other !is User) {
return false
}
return other.name == name
}
}
在我们重写 equals
方法之后,输出的结果确实就是 true
接着来看看另一种常见的例子,Set
集合中存了一些User
对象, 现在给定一个User对象判断是否存在在这个集合中
val set = hashSetOf(User("Herman"), User("Taomm"))
println(set.contains(user1))
虽然User类我们已经实现了equals
方法, 这个例子输出的结果却是 false, 这是由于User类还缺少hashCode方法, 这里违反了Hashcode的通用约定: 如果两个对象相等,那么它们的hashCode必须相同, 再给User添加HashCode方法后输出的结果就正确了
override fun hashCode(): Int {
return name.hashCode() * 31
}
在Java中以上的两个方法equals
hashCode
再需要判断对象是否相等的时候通常都需要重写, 而在Kotlin提供了数据类的来帮助我们自动生成这两种方法,让代码看起来更加的简洁. 数据类使用的关键字是 data
,接下来我们用数据类来改造上面的例子看看输出的结果
data class User(val name: String)
fun main(args: Array<String>) {
val user1 = User("Herman")
val user2 = User("Herman")
println("user1 == user2 => ${user1 == user2}")
val set = hashSetOf(User("Herman"), User("Taomm"))
println("set.contains(user1) => ${set.contains(user1)}")
}
上面的输出结果满足我们的需求, 同时代码也会更加简洁
数据类同时还会多生成一个copy方法,方便对象的复制,新的对象有全新的生命周期,不会影响原有对象, 同时在复制的时候还可以重写设置某些属性的值
val copyUser = user1.copy(name = "Herman2")
println(copyUser)
数据类的属性虽然没有要求一定是val,但是建议尽量使用val来保证数据类的不可变性, 如果需要修改对象可以使用copy
委托类
现在我们来看个例子,我需要实现接口Collection
, 接口的方法代理给一个List实例来完成
class DelegateCollection<T> : Collection<T> {
private val list = arrayListOf<T>()
override val size: Int
get() = list.size
override fun contains(element: T): Boolean {
return list.contains(element)
}
override fun containsAll(elements: Collection<T>): Boolean {
return list.containsAll(elements)
}
override fun isEmpty(): Boolean {
return list.isEmpty()
}
override fun iterator(): Iterator<T> {
return list.iterator()
}
}
类似于这种的委托类在Java中十分的常见, 这里面有很多模版代码, Kotlin可以通过 by
关键字实现委托省略到这些模版代码,让代码更加简洁
class DelegateCollection<T>(private val list: List<T> = arrayListOf()) : Collection<T> by list
我们依然可以重写个别方法来实现自己的逻辑
class DelegateCollection<T>(private val list: List<T> = arrayListOf()) : Collection<T> by list {
override fun contains(element: T): Boolean {
//todo: 写自己的逻辑
return list.contains(element);
}
}
原文链接: http://herman7z.site