Skip to content

数据类

在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