2021年6月1日火曜日

Kotlin の sealed interface が必要になる例

(本当は Compose のコード例(State/MutableState)にしたかったんだけど、まだ Jetpack Compose は Kotlin 1.5 に対応してないので sealed interface 使えないんだよね...)


ViewModel で持ってる LiveData を Activity で observe してるとする。 class MainActivity : AppCompatActivity() { private val viewModel: MainViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) viewModel.state.observe(this) { when (it) { is State.Data -> { println(it.value) } State.Loading -> { } } } } } class MainViewModel : ViewModel() { private val _state = MutableLiveData<State>() val state: LiveData<State> get() = _state fun doSomething() { val state = _state.value if (state is State.Data) { state.mutableValue = Random.nextInt() } } } sealed class State { object Loading : State() data class Data(val id: String) : State() { // 変更できるのは MainViewModel からだけにしたいが、 // private にすると MainViewModel からも見えなくなる var mutableValue: Int = -1 val value: Int get() = mutableValue } } ↑ State.Data が持つ mutableValue は MainViewModel からのみ変更できるようにしたい。

mutableValue に private は MainViewModel から見えなくなるのでダメ。 private var mutableValue: Int = -1 これもダメ。 private sealed class State { private data class Data(val id: String) : State() { Data を top level にすると private をつけても MainViewModel から見えるけど、MainActivity から見えなくなるのでダメ。 sealed class State object Loading : State() // MainViewModel から mutableValue は見えるが // Data が MainActivity からは見えなくなる private data class Data(val id: String) : State() { var mutableValue: Int = -1 val value: Int get() = mutableValue }

ということで sealed interface を使います。 class MainViewModel : ViewModel() { private val _state = MutableLiveData<State>() val state: LiveData<State> get() = _state fun doSomething() { val state = _state.value if (state is DataImpl) { state.mutableValue = Random.nextInt() } } } sealed interface State object Loading : State sealed interface Data : State { val value: Int } private class DataImpl(val id: Int) : Data { // private class なので変更できるのは同じファイルからだけ var mutableValue: Int = id override val value: Int get() = mutableValue }

0 件のコメント:

コメントを投稿