Kotlin의 변수에 추가될 수 있는 'private set' 이라는 상태? 가 있다.
var variable = 0
private set
과 같은 형태로 선언되며, 특이하게도 val 에는 사용할 수 없다.
private set은 getter / setter가 자동 적용되는 Kotlin에서 setter를 private로 바꿔준다.
즉, 어디에서든 읽을수는 있으나, 쓰는 것은 해당 변수가 선언된 클래스에서만 가능하게 된다.
이로 인해 어느정도 데이터 일원화에 도움을 줄 수 있을 것 같다.
(데이터 일원화란, 특정 유형의 데이터들은 모두 한 곳에서 관리한다 는 의미이다.)
그렇다면 여기서 궁금했던 부분이 있다.
우리가 MVVM 및 Clean Architecture를 적용하면서 데이터 일원화를 위해 사용했던
private val _liveData = MutableLiveData<Int>()
val liveData : LiveData<Int> = _liveData
와 같은 형식과 무엇이 다르며, 왜 이런 경우에는 private set을 사용하지 않고 변수를 두개 선언해서 사용할까?
둘 모두 setter를 private으로 두기 위함이며, 데이터 일원화를 위해 필요한 작업이다.
그래서 직접 실험해보았다.
주로 데이터 일원화를 사용하는 ViewModel 레이어에 4가지의 테스트 변수들을 생성했다.
var testData = 0
private set
var testMutableList = mutableListOf<Int>()
private set
var testLiveData = MutableLiveData<Int>()
private set
private val _testLiveData2 = MutableLiveData<Int>()
val testLiveData2 : LiveData<Int> = _testLiveData2
위쪽부터 Int, List, private set을 적용한 MutableLiveData, 일반적으로 사용하는 일원화 방식의 LiveData 이다.
그리고 해당 ViewModel의 데이터들을 View 레이어에서 변경하려고 시도해보았다.
viewModel.testData = 3
viewModel.testMutableList.add(3)
viewModel.testLiveData.value = 3
viewModel.testLiveData2.value = 3
결과는 1, 4번은 적용되지 않고 2, 3번은 변경이 잘 적용되었다.
이로써 얻을 수 있는 결론이 하나 있다.
private set으로 적용한 setter는 내부의 값 혹은 value가 아닌, 해당 대분류?의 데이터 자체 (List, LiveData) 가 변경되는 것을 막아준다.
그러므로 Int는 그 자체적으로 대분류?적인 데이터이므로 적용이 불가능했고
List, LiveData는 대분류?의 변경이 아닌 내부의 값들의 변경이므로 Mutable의 특성을 따라 변경이 가능했던 것으로 보인다.
그러므로 private set은 무언가를 포함하는 타입이 아닌 String, Int, Boolean 등의 타입에서 사용하는 것이 좋아 보인다.