Введите безопасное использование общих закрытых классов - PullRequest
0 голосов
/ 21 февраля 2019

Я нашел интересную вещь, когда я пишу общий запечатанный класс.Вот первая версия:

// 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.Похоже недокументированная экстралингвистическая функция .

1 Ответ

0 голосов
/ 21 февраля 2019

Дисперсия не работает в конце.Response<MyInterfaceImpl> не является Response<MyInterface> и, следовательно, Failure и Cancelled не могут быть использованы.Даже если вы не используете гернерный тип, вы все равно объявляете его.

При вводе out T вы получите эффект, подобный ? extends T в Java .

Тогда для Nothing у вас есть:

Ничто не имеет экземпляров.Вы можете использовать Nothing, чтобы представить «значение, которое никогда не существует».

Это также означает, что оно является подтипом всего и, следовательно, также работает для обобщений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...