覆盖 Kotlin 数据类的 getter [英] Override getter for Kotlin data class
问题描述
给定以下 Kotlin 类:
Given the following Kotlin class:
data class Test(val value: Int)
如何覆盖 Int
获取器,使其在值为负时返回 0?
How would I override the Int
getter so that it returns 0 if the value negative?
如果这是不可能的,有哪些技术可以达到合适的结果?
If this isn't possible, what are some techniques to achieve a suitable result?
推荐答案
在每天花费几乎一整年时间编写 Kotlin 之后,我发现尝试像这样覆盖数据类是一种不好的做法.对此有 3 种有效方法,在我介绍它们之后,我将解释为什么其他答案建议的方法很糟糕.
After spending almost a full year of writing Kotlin daily I've found that attempting to override data classes like this is a bad practice. There are 3 valid approaches to this, and after I present them, I'll explain why the approach other answers have suggested is bad.
让创建
数据类
的业务逻辑在调用具有错误值的构造函数之前将值更改为 0 或更大.这可能是大多数情况下的最佳方法.
Have your business logic that creates the
data class
alter the value to be 0 or greater before calling the constructor with the bad value. This is probably the best approach for most cases.
不要使用数据类
.使用常规的 class
并让您的 IDE 为您生成 equals
和 hashCode
方法(或者不,如果您不需要它们).是的,如果对象的任何属性发生更改,您将必须重新生成它,但您可以完全控制对象.
Don't use a data class
. Use a regular class
and have your IDE generate the equals
and hashCode
methods for you (or don't, if you don't need them). Yes, you'll have to re-generate it if any of the properties are changed on the object, but you are left with total control of the object.
class Test(value: Int) {
val value: Int = value
get() = if (field < 0) 0 else field
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is Test) return false
return true
}
override fun hashCode(): Int {
return javaClass.hashCode()
}
}
在对象上创建一个额外的安全属性来执行您想要的操作,而不是拥有一个被有效覆盖的私有值.
Create an additional safe property on the object that does what you want instead of having a private value that's effectively overriden.
data class Test(val value: Int) {
val safeValue: Int
get() = if (value < 0) 0 else value
}
其他答案建议的糟糕方法:
data class Test(private val _value: Int) {
val value: Int
get() = if (_value < 0) 0 else _value
}
这种方法的问题在于数据类并不是真正意义上的像这样改变数据.它们实际上只是用于保存数据.像这样覆盖数据类的 getter 意味着 Test(0)
和 Test(-1)
不会 equal
并且会有不同的 hashCode
,但是当你调用 .value
时,它们会得到相同的结果.这是不一致的,虽然它可能对你有用,但你团队中的其他人看到这是一个数据类,可能会意外地误用它,而没有意识到你是如何改变它/使它无法按预期工作的(即这种方法不会t 在 Map
或 Set
中正常工作).
The problem with this approach is that data classes aren't really meant for altering data like this. They are really just for holding data. Overriding the getter for a data class like this would mean that Test(0)
and Test(-1)
wouldn't equal
one another and would have different hashCode
s, but when you called .value
, they would have the same result. This is inconsistent, and while it may work for you, other people on your team who see this is a data class, may accidentally misuse it without realizing how you've altered it / made it not work as expected (i.e. this approach wouldn't work correctly in a Map
or a Set
).
这篇关于覆盖 Kotlin 数据类的 getter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!