Rob Elliot
04/28/2022, 10:14 PMcopy method delegate to an operator fun invoke on the class's companion object that took the same parameters but was able to return a more flexible return type.
It's a shame that you have to put all the invariant checking in the data class's init, and so have to fail it with exceptions.Rob Elliot
04/28/2022, 10:22 PMdata class Foo private constructor(val x: Int, val y: Int) {
companion object {
operator fun invoke(x: Int, y: Int): Result<Foo> =
if (x < y) Result.failure(Exception("oh no"))
else Result.success(Foo(x, y))
}
}
It would be nice if Foo(2, 1).copy(y = 3) returned a Result<foo>, instead of a Foo bypassing the invariant check.Rob Elliot
04/28/2022, 10:25 PMdata class Foo(val x: Int, val y: Int) {
init {
require(x >= y)
}
}
and callers only find out at runtime that it can go wrong.
(Of course you could keep the constructor private and have the operator fun invoke as well, and have the init check just for when copy is called, but duplicating the checks feels very in elegant and it all starts to get a bit noisy when one of the joys of data classes is how little syntax they require.)hfhbd
04/29/2022, 9:56 AMinit block instead, which is more kotlinisher IMHO.Rob Elliot
04/29/2022, 10:00 AMcopy to delegate to an operator fun invoke that returns... well, anything really, if the data class's constructor is private.Rob Elliot
04/29/2022, 10:01 AMnull. Personally I'm not a fan of things that just silently don't work without telling you why. And it may be that the caller can behave differently depending on the details of why it failed.