当属性之一是函数时,Kotlin 数据类相等

问题描述

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

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

解决方法

我不认为这是可能的,恐怕。

您当然可以检查引用相等性(在这种情况下为 =====,因为函数通常不会覆盖 equals())。这会给你一个明确的答案,你有对同一个函数实例的引用。但这不会检查结构是否相等,因此将问题中的两个 lambda 报告为不同。

您可以通过检查它们的 .javaClass 属性来检查这两个函数是否是同一类的实例。如果相同,那将意味着它们进行相同的处理——尽管我认为它们仍然可以有不同的变量/捕获。但是,如果不同,那不会告诉你任何事情。就连问题中的简单例子都是不同的类......

当然,您不能将它们视为“黑匣子”——尝试所有可能的输入并检查它们的输出是不可行的。 (即使假设它们是没有副作用的纯函数,这通常也不是真的!)

可能能够从类加载器中获取他们的字节码,并进行比较,但我真的不推荐它——这将是很多不必要的工作,你必须考虑到类名等的差异,它可能会有很多误报,我再次认为它可以为两个由于不同的参数/捕获而表现不同的函数返回相同的代码。

所以不,我认为这在 JVM 语言中是不可能的。

你想通过这个实现什么,还有其他方法吗? (例如,如果这些函数在你的控制之下,你能安排引用相等来做你需要的吗? 或者你可以使用带有额外属性的函数对象,给出一个 ID 或其他你可以比较的东西?)