Я нашел интересную вещь, когда я пишу общий запечатанный класс.Вот первая версия:
// 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>()
допустим, у нас также есть функция запроса , например:
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>
}
Первый вопрос : Failure
и Cancelled
не используют T
для позиций входа / выхода , почему этот бросок не отмечени мне нужно это подавить?
Через некоторое время Константин покажет мне решение, как объявить тип безопасного запечатанного класса :
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
.Похоже недокументированная экстралингвистическая функция .