如何在kotlin中制作密封类通用?

时间:2017-05-29 13:31:10

标签: kotlin

是否可以使用下面的AsyncResult类来防止在UserDataAppResult和CreateUserResult中重新定义InFlight,Error和InFlight?

//TODO: use this to make the below classes generic?
sealed class AsyncResult{
  object InFlight : AsyncResult()
  data class Error(val errorMessage: String) : AsyncResult()
  data class Loaded<out T>(val users: T) : AsyncResult()
}

sealed class UserDataAppResult : AppResult() {
  object InFlight : UserDataAppResult()
  data class Error(val errorMessage: String) : UserDataAppResult()
  data class Loaded(val users: List<User>) : UserDataAppResult()
}

sealed class CreateUserResult : AppResult() {
  object InFlight : CreateUserResult()
  data class Error(val errorMessage: String) : CreateUserResult()
  data class Loaded(val users: User) : CreateUserResult()
}

以上代码是否可能如下所示?

sealed class AsyncResult{
  class InFlight : AsyncResult()
  data class Error(val errorMessage: String) : AsyncResult()
  data class Loaded<out T>(val users: T) : AsyncResult()
}

sealed class UserDataAppResult : AsyncResult()
sealed class CreateUserResult : AppResult()

val activeUsers: Flowable<UserDataAppResult> = appDatabase.userDao().getActiveUsers(appSettings.currentLanguage.ordinal)
    .map<UserDataAppResult> { UserDataAppResult.Loaded(it) }
    .onErrorReturn { UserDataAppResult.Error(it.localizedMessage) }
    .startWith(UserDataAppResult.InFlight)
    .observeOn(AndroidSchedulers.mainThread())
    .share()

fun createUser(): Flowable<CreateUserResult> {

  val userId = UUID.randomUUID().toString()
  val user = User()
  user.id = userId
  return appDatabase.userDao().insertAll(user)
      .map <CreateUserResult> { CreateUserResult.Loaded(user) }
      .onErrorReturn { CreateUserResult.Error(it.localizedMessage) }
      .startWith(CreateUserResult.InFlight)
}

目前找不到有意义的UserDataAppResult.Error。 但是,是否可以重用AppResult密封类层次结构并引入新类型。

3 个答案:

答案 0 :(得分:4)

Kotlin不可能。您使用的每种类型都必须在某处显式声明类。即使在超类中声明嵌套类的情况下,编译器也不会隐式创建类。

对于您的问题,我建议您重写代码,将两个基于继承的层次结构组合到两个组合继承和组合之一,或者只是以某种方式重构层次结构,例如(我想结果的确切实例)如果它不是Loaded),那将与你无关:

sealed class AsyncResult {
    object InFlight : AsyncResult()
    data class Error(val errorMessage: String) : AsyncResult()
    sealed class Loaded<out T>(val result: T) : AsyncResult() {
        sealed class UserDataAppResult(users: List<User>) : Loaded<List<User>>(users)
        sealed class CreateUserResult(user: User) : Loaded<User>(user)
    }
}

答案 1 :(得分:0)

通过Google指南:https://developer.android.com/jetpack/docs/guide

sealed class Resource<T>(
        val data: T? = null,
        val message: String? = null
) {
    class Success<T>(data: T) : Resource<T>(data)
    class Loading<T>(data: T? = null, var refreshing: Boolean = false) : Resource<T>(data)
    class Error<T>(data: T? = null, message: String) : Resource<T>(data, message)
}

答案 2 :(得分:0)

您的Object在Kotlin中不能具有泛型,但是可以通过以下示例简单地解决此问题:

sealed class ResponseState<out T> {
    object Loading : ResponseState<Nothing>()
    data class Error(val throwable: Throwable) : ResponseState<Nothing>()
    data class Success<T>(val item: T) : ResponseState<T>()
}