当其中一个属性是函数时,Kotlin数据类相等

mrwjdhj3  于 2023-03-24  发布在  Kotlin
关注(0)|答案(3)|浏览(203)

我想知道一个数据类是否有一个属性是函数,例如:

data class Holder(val x: Data, val f: () -> Unit)

因为下面的测试失败了。

val a = {}
val b = {}
Assert.assertEquals(a, b)

**更新:**此用例可能是具有

data class ButtonDescriptor(val text: String, val onClick: () -> Unit)

然后在执行distinctUntilChanged()时将其流到UI

3phpmpom

3phpmpom1#

恐怕这不可能。
当然,你可以检查引用相等性(===,或者在本例中是==,因为函数通常不会覆盖equals())。 这会给予你一个明确的答案,你有相同的函数示例的引用。 但这不会检查结构相等性,因此报告问题中的两个lambda表达式是不同的。
你可以通过检查.javaClass属性来检查这两个函数是否是同一个类的示例。 如果相同,那就意味着它们执行相同的处理-尽管我认为它们仍然可以有不同的变量/捕获。 然而,如果不同,那也不会告诉你任何事情。 即使是问题中的简单例子也是不同的类...
当然,你不能把它们当作“黑盒”来检查--尝试每一个可能的输入并检查它们的输出是不可行的 (即使假设它们是没有副作用的纯函数,这通常是不正确的!)
你 * 也许 * 可以从类加载器中获取它们的字节码,并进行比较,但我真的不建议这样做-这将是很多不必要的工作,你必须考虑到类名等的差异,它可能会有很多假阴性,而且我认为它可能会为两个函数返回相同的代码,而这两个函数由于不同的参数/捕获而表现不同。
所以不,我不认为这在JVM语言中是可能的。
你想用它来实现什么,还有其他方法吗? (例如,如果这些函数在你的控制之下,你能安排引用相等来做你需要的事情吗? 或者你能使用带有额外属性的函数对象来提供ID或其他你可以比较的东西吗?)

6tdlim6h

6tdlim6h2#

当你创建数据类时,如果你通过引用传递函数,它将与DiffUtils和distinctUntilChanged()一起工作。函数引用不会像lambda那样破坏数据类的isEquals()方法。
例如,为onClick创建一个函数:

private fun onClick() { // handle click }

并创建数据类,如

BottomDescriptor("some text", ::onClick)
pxy2qtax

pxy2qtax3#

你可以做的是创建一个扩展函数定义的数据类,然后Kotlin将能够确定数据类的相等性。

import kotlinx.*

fun main() {
    val functionHolderA = FunctionHolder(Function("Test"))
    val functionHolderB = FunctionHolder(Function("Test"))
    println(functionHolderA == functionHolderB)
}

data class FunctionHolder(val function: () -> String)

data class Function(val name: String): () -> String {
    override fun invoke() = name
}

Kotlin Playground

相关问题