kotlin

kotlin - enum , object, state 관리(외부 접속 시) -> abstract class(interface)로 변경 -> sealed class/interface로 변경

slow333 2023. 3. 27. 21:57

enum class를 이용한 state machine을 만드는 방법

enum class Result {
   SUCCESS,
   ERROR,
   IDLE,
   LOADING
}

fun getResult(result: Result) {
   return when (result) {
      Result.SUCCESS -> println("성공")
      Result.ERROR -> println("애러 남")
      Result.IDLE -> println("한가 함")
      Result.LOADING -> println("로딩 중...")
   }
}

object Repository {
   private var loadState: Result = Result.IDLE
   private var dataFetched: String? = null
   fun startFetch() {
      loadState = Result.LOADING
      dataFetched = "data"
   }

   fun finishedFetch() {
      loadState = Result.SUCCESS
      dataFetched = null
   }

   fun error() {
      loadState = Result.ERROR
   }

   fun getCurrentState(): Result {
      return loadState
   }
}

fun main() {
   Repository.startFetch()
   getResult(result = Repository.getCurrentState())
   Repository.finishedFetch()
   getResult(result = Repository.getCurrentState())
   Repository.error()
   getResult(result = Repository.getCurrentState())
}

enum class에 상태 정보를 주기 위해 abstract class(interface)로 enum class를 변경

//enum class Result {
//   SUCCESS,
//   ERROR,
//   IDLE,
//   LOADING
//}

//abstract class Result -> 적용 시에 () 필요

interface Result

data class Success(val dataFetched: String?): Result
data class Error(val exception: Exception): Result
object Loading : Result
object NotLoading: Result

fun getResult(result: Result) {
   return when (result) {
      is Success -> println(result.dataFetched?: "Ensure you start data fetched")
      is Error -> println(result.exception.toString())
      is Loading -> println("로딩 중...")
      is NotLoading -> println("한가 함...")
      else -> { println("NA")} // sealed로 바꾸면 없어도 됨
   }
}

object Repository {
   private var loadState: Result = NotLoading
   private var dataFetched: String? = null
   fun startFetch() {
      loadState = Loading
      dataFetched = "data"
   }
   fun finishedFetch() {
      loadState = Success(dataFetched)
      dataFetched = null
   }
   fun error() {
      loadState = Error(exception = Exception("Loading is the first action"))
   }
   fun getCurrentState(): Result {
      return loadState
   }
}

fun main() {
   Repository.startFetch()
   getResult(result = Repository.getCurrentState())
   Repository.finishedFetch()
   getResult(result = Repository.getCurrentState())
   Repository.error()
   getResult(result = Repository.getCurrentState())
}

sealed class로 변경하여 getResult에서 else문을 없에고 sealed class(interface) 안에 여러 data class를 담음

import java.io.IOException

sealed interface Result

data class Success(val dataFetched: String?): Result
data class Error(val exception: Exception): Result
object Loading : Result
object NotLoading: Result

sealed interface Failure: Result {
   data class CustomFailure(val customFailure: IOException) : Failure
   data class AnotherCustomFailure(val anotherCustomFailure : NullPointerException) : Failure
}

fun getResult(result: Result) {
   return when (result) {
      is Success -> println(result.dataFetched?: "Ensure you start data fetched")
      is Error -> println(result.exception.toString())
      is Loading -> println("로딩 중...")
      is NotLoading -> println("한가 함...")
      is Failure.CustomFailure -> println(result.customFailure.toString())
      is Failure.AnotherCustomFailure -> println(result.anotherCustomFailure.toString())
//      else -> { println("NA")} -> sealed로 바꾸면 없어도 됨
   }
}

object Repository {
   private var loadState: Result = NotLoading
   private var dataFetched: String? = null
   fun startFetch() {
      loadState = Loading
      dataFetched = "data"
   }
   fun finishedFetch() {
      loadState = Success(dataFetched)
      dataFetched = null
   }
   fun error() {
      loadState = Error(exception = Exception("Loading is the first action"))
   }
   fun getCurrentState(): Result {
      return loadState
   }
   fun anotherFailure() {
      loadState = Failure.AnotherCustomFailure(anotherCustomFailure = NullPointerException("some null point exception"))
   }
   fun customFailure(){
      loadState = Failure.CustomFailure(customFailure = IOException("Some Io error invoked"))
   }
}

fun main() {
   Repository.startFetch()
   getResult(result = Repository.getCurrentState())
   Repository.finishedFetch()
   getResult(result = Repository.getCurrentState())
   Repository.error()
   getResult(result = Repository.getCurrentState())

   Repository.anotherFailure()
   getResult(result = Repository.getCurrentState())
   Repository.customFailure()
   getResult(result = Repository.getCurrentState())
}