此问题的范围比Extract common objects from sealed class in kotlin和Android - How to make sealed class extend other sealed class?更广,因此不是重复问题
我有多个密封类,它们表示各种API调用的结果,每个调用都有一组共同的预期结果(成功、网络错误、意外错误),但每个调用都可能引入自己的结果类型(如“找不到用户”或“错误ID”)。
为了避免将相同的子类复制到每个密封类中,我想创建一个包含所有公共结果类型的“基”类型,而每个密封类可以添加其特定的子类:
interface BaseApiCallResult {
data class Success(val data: String) : BaseApiCallResult
data class UnexpectedError(val error: Throwable) : BaseApiCallResult
data class NetworkError(val error: ApolloException) : BaseApiCallResult
}
sealed class ApiCallResult1 : BaseApiCallResult {
data class WrongID(val id: Int) : ApiCallResult1()
}
sealed class ApiCallResult2 : BaseApiCallResult {
data class UserDoesNotExist(val userid: Long) : ApiCallResult2()
}
sealed class ApiCallResult3 : BaseApiCallResult {
data class NameAlreadyTaken(val name: String) : ApiCallResult3()
}
问题是“基”中的子类不能被视为“子”类:
fun apiCall1(): ApiCallResult1 {
// won't compile, since BaseApiCallResult.UnexpectedError is not ApiCallResult1
return BaseApiCallResult.UnexpectedError(Exception(""))
}
fun useApi() {
when(val result = apiCall1()) {
is ApiCallResult1.WrongID -> { }
// compile error: Incompatible types
is BaseApiCallResult.Success -> { }
is BaseApiCallResult.UnexpectedError -> { }
is BaseApiCallResult.NetworkError -> { }
}
}
Android - How to make sealed class extend other sealed class?的解决方案可能适用于此处,但对于大量的密封类(我预计可能需要几十个这样的类),它变得相当笨拙
interface BaseApiCallResult {
data class Success(val data: String) : Everything
data class UnexpectedError(val error: Throwable) : Everything
data class NetworkError(val error: ApolloException) : Everything
}
sealed interface ApiCallResult1 : BaseApiCallResult {
data class WrongID(val id: Int) : ApiCallResult1()
}
sealed interface ApiCallResult2 : BaseApiCallResult {
data class UserDoesNotExist(val userid: Long) : ApiCallResult2
}
sealed interface ApiCallResult3 : BaseApiCallResult {
data class NameAlreadyTaken(val name: String) : ApiCallResult3
}
// adding each new sealed interface here seems like a hack
interface Everything : BaseApiCallResult, ApiCallResult1, ApiCallResult2, ApiCallResult3
另外,使用上面的解决方案,每个when {...}
都会抱怨Everything
的情况没有得到处理。我可以放弃使用Everything
,但是我必须列出每个“基本”子类中的所有接口,这简直太可怕了:
// just imagine how would it look if there were 30 ApiCallResult classes
interface BaseApiCallResult {
data class Success(val data: String) : BaseApiCallResult, ApiCallResult1, ApiCallResult2, ApiCallResult3
data class UnexpectedError(val error: Throwable) : BaseApiCallResult, ApiCallResult1, ApiCallResult2, ApiCallResult3
data class NetworkError(val error: ApolloException) : BaseApiCallResult, ApiCallResult1, ApiCallResult2, ApiCallResult3
}
有没有更好的办法来处理这种情况?
1条答案
按热度按时间mzmfm0qo1#
您必须将ApiResult与ApiMethodResult分开,它们不应是亲属。
Kotlin已经有了结果类型,您可以使用它:
或者您可以自行实现: