编写通用密封类时,我发现了有趣的事情。这是第一个版本:
// sample interface and implementation
interface MyInterface
class MyInterfaceImpl : MyInterface
sealed class Response<T: MyInterface>
data class Success<T: MyInterface>(val payload: T) : Response<T>()
data class Failure(val errorCode: Int) : Response<MyInterface>()
object Cancelled : Response<MyInterface>()
假设我们也有 request函数,如下所示:
fun <T: MyInterface> requestObject(cls : KClass<T>): Response<T> = TODO("Request")
现在在使用端,我们有错误:
fun test() = when (val response = requestObject(MyInterfaceImpl::class)) {
is Success -> print("Payload is ${response.payload}") // Smart cast perfectly works!
is Failure -> print("Error code ${response.errorCode}") // Incomparable types: Failure and Response<MyInterfaceImpl>
Cancelled -> print("Request cancelled") // Incomparable types: Cancelled and Response<MyInterfaceImpl>
}
第一个问题:对于{em>进/出位置,
Failure
和Cancelled
并未使用T
,这是为什么未选中,我需要抑制它吗?
过一会儿,Konstantin向我展示了如何声明类型安全密封类的解决方案:
sealed class Response<out T: MyInterface> // <-- out modifier here
data class Success<T: MyInterface>(val payload: T) : Response<T>()
data class Failure(val errorCode: Int) : Response<Nothing>() // <-- Nothing as type argument
object Cancelled : Response<Nothing>() // <-- Nothing as type argument
此声明就像一个咒语,现在我有疑问:
第二个问题:为什么需要在此处编写
out
修饰符?第三个问题:为什么
Producer<Nothing>
是Producer<MyInterface>
的子类型?根据协变的定义:如果Producer<A>
是Producer<B>
的子类型,则A
是B
的子类型,但是Nothing
不是MyInterface
的子类型。看起来像未记录的语言外功能。
答案 0 :(得分:1)
最终无法解决差异。 dates
不是numbers
,因此无法使用Response<MyInterfaceImpl>
和Response<MyInterface>
。即使您没有使用gerneric类型,您仍然可以声明它。
放置Failure
时,在 Java 中,您会得到类似Cancelled
的效果。
然后Nothing
,您拥有:
没有任何实例。您可以使用Nothing来表示“永远不存在的值”。
这也意味着它是所有内容的子类型,因此也适用于泛型。