Intereting Posts
AndroidAnnotations – ViewById не может использоваться для частного элемента Объявление поля POJO, значение init или null Retrofit2 Добавить дополнительную строку в объект Body Позиция метки `@` в Котлине, обозначая приемник с `this` Как начать второй наблюдаемый после получения результата от первого наблюдаемого в андроиде? Kotlin и Spring Data JPA создает PropertyReferenceException Обновлено до Android Studio 3.0. Получение ошибки «Kotlin не настроено» Есть ли способ переопределить свойство setter в расширяющемся классе в Котлине Возможно ли использовать String как PrimaryKey в Android Room Неверные типы в обработчике аннотации kotlin Как проверить функцию kotlin varargs с помощью mockito Преобразование Kotlin SAM с частным внутренним интерфейсом Java? Почему знак плюса должен быть в конце строки, а не в начале на следующей строке? Почему в Котлине правильны оба окна box1 и val box2? У меня есть два метода расширения Kotlin для одного и того же класса, но с разными генерическими сигнатурами и компилятор жалуется

Подклассификация класса для изменения переменной параметра типа в Котлине

Этот вопрос вытекает из моего предыдущего вопроса о Generic Kotlin . Пожалуйста, посмотрите там дополнительную информацию о мотивации этого вопроса.

У меня есть класс, который принимает параметр неограниченного типа

trait Handler<T> { fun handle(result: T) } 

Мне нужно создать экземпляр Handler где T является List<O> , и поэтому является неизменным. Моя мысль заключалась в подклассе Handler и комментировании его как потребителя (т. Е. При использовании)

 trait ListHandler<in T>: Handler<List<T>> { } 

Однако это дает мне ошибку, которая говорит: «Параметр T объявлен как« in », но встречается в« инвариантном »положении в Handler<List<T> "

Что означает ошибка, и есть ли способ обойти ее?

Эта ошибка означает, что для всех компиляторов ваши объявления могут привести к сбою во время выполнения. Имейте в виду, что при проверке ListHandler компилятор не знает, какие члены определены внутри Handler , все, что он знает, – это то, что Handler был успешно проверен на соответствие типу и что его подпись говорит о том, что параметр типа является инвариантным. Это необходимо, потому что Handler может быть изменен позже и перекомпилирован без перекомпиляции ListHandler :

 trait Handler<T> { fun handle(result: T) fun get() : T } 

С таким заявлением легко написать фрагмент кода:

 // an ill-behaved ListHandler class HandlerImpl<T> : ListHandler<T> { private var storage: List<T> = listOf() override fun handle(result: List<T>) { storage = result } override fun get(): List<T> = storage } // Code using it, that breaks fun main(args: Array<String>) { val anyHandler = HandlerImpl<Any>() anyHandler.handle(listOf(1, 2, 3)) val problematic: ListHandler<String> = anyHandler // The following line requires an element to be a String, but it is an Int problematic.get()[0].length() } 

Результат:

 Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String 

Смотрите полный код здесь .