data class NonNegativeDouble(val value: Double) {
init {
require(value >= 0) { "Value must be greater or equal to 0." }
}
override fun toString() = value.toString()
}
data class NonNegative(val nonNegativeDouble: NonNegativeDouble)
If you want to protect your data constraints this way is probably better.
Thanks for the alternative! However, unless I kept the check in setValue(), which would then duplicate the check in setValue() and getValue(), the property would have negative value (even if inaccessible). (Further, if the value is read more often than written, this would run the check on every get . . . .)
Moving the goal post a bit: if the value is only allowed to be initialized to ≥ 0 and later set to ≥ 0 or to retain its present value:
class NonNegDelegate(initVal: Double) {
private var _nonNeg: Double = if (initVal >= 0.0) initVal else 0.0
operator fun getValue(thisRef: Any?, property: KProperty<*>): Double {
return _nonNeg
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Double) {
_nonNeg = if (value >= 0.0) value else _nonNeg
}
}
is there an alternative that uses property delegation but doesn’t replicate the check?
class NonNegDelegate(initVal: Double) {
private var nonNeg: Double = initVal
set(value) {
require(value >= 0) { "Value must be greater or equal to 0." }
field = value
}
init {
require(nonNeg >= 0) { "Value must be greater or equal to 0." }
}
operator fun getValue(thisRef: Any?, property: KProperty<*>): Double = nonNeg
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Double) {
nonNeg = value
}
}
The only problem is as you probably noticed is that an initial field initialization doesn’t use setter, so the check needs to be done twice.
Hm, I do like this one better. I guess because the logic is “closer” to the field? One less level of indirection? It’s good to know that one could call setValue() in the other solution though.
BTW, the last function assignment cannot be an assignment, according to the compiler:
operator fun setValue(thisRef: Any?, property: KProperty<*>?, value: Double) = _nonNeg = value
needs to be:
operator fun setValue(thisRef: Any?, property: KProperty<*>?, value: Double) { _nonNeg = value }