Kotlin copy for data class with apply to this object


#1

Good afternoon, I encountered a problem that similar constructions are now located throughout the code - state = state.copy (points = it), I would like to see something like state.applyCopy (points = it), I would be able to do it , if there was an opportunity to write extesions functions for data classes, is it possible to solve this problem with existing language features (without prescribing a method for each class) or is it possible to expect that this feature will appear in the future?


#2

Are you looking for something like:

state.apply {
    points = it
}

http://kotlinlang.org/api/latest/jvm/stdlib/kotlin/apply.html


#3

Thanks but state is immutable object and has all fileds as val.


#4

It seems to me that you want to define a method applyCopy, which, when called as state.applyCopy(...) updates the actual variable state and not just the object that state points to. That would require the variable to be passed by reference, which is impossible in Kotlin.


#5

Interesting idea. I’ve specifically needed this kind of construct before and resorted to using a builder or simply turning all my data class’s vals into vars.

This could be implemented by way of each data class generating a secondary class with all vars and including a copy method. state.copy { /* receiver is type State.Builder */ }


#6

No, I just want to make this state = state.copy (points = it) a lacon. In real example state equal liveData.value in MutableLiveData and i need to set a new value for the observer pattern to be executed. Real code - viewState.value = viewState.value?.copy(connectionState=connectionState) and on other side:
reducer.viewState.observeThis { (!isInstanceSaved) render(it) }


#7

Ah, I misunderstood.
So you’re basically wanting to use it within the copy method?

You could do something like the following:

state = state.run { copy(points = points) }
state = state.let { it.copy(points = it.points) }
state = with(state) { copy(points = points) }

#8

You are thinking that this - state = state.run { copy(points = points) } better than this - state = state.copy(points = points)?


#9

I’m not saying that using run {...} is better, I’m saying it works without new language features.
To make sure we’re on the same page, here’s what I think you’re wanting but I’ve added an explicit this with a label:

state = state.copy(points = this@State.points)

// Which is the same thing as:
state = state.copy(points = points)

// And if "points" is the only param, then it's the same as:
state = state.copy(points) // this@State.points

Changing the receiver is only possible within an extension function (or extension lambda). The examples I provided are the closest alternative I can think of that work without adding language features.