Kotlin - несоответствие типов с generi c тип возвращаемого значения и подкласс - PullRequest
0 голосов
/ 30 марта 2020

Я надеюсь, что все остаются здоровыми среди этой пандемии c:)

Я мог бы помочь, чтобы выяснить, что я делаю здесь неправильно, TIA! Кроме того, я немного новичок в Kotlin, извините, если это глупый вопрос.

Я пытаюсь расширить класс и реализовать интерфейс, определенный в библиотеке java (AndroidX ). Однако, когда я пытаюсь реализовать функцию интерфейса, я получаю ошибку несоответствия типов с моим возвращаемым значением. Поскольку я использую интерфейс, определенный в библиотеке AndroidX, просто изменить сигнатуру функции интерфейса, чтобы она была построена, не вариант.

Я в основном конвертирую этот другой SO-ответ в Kotlin: { ссылка }

Информация о машине разработчика / IDE: Android Studio 3.6.1 Build # AI-192.7142.36.36.6241897, построена 26 февраля 2020 г. Версия среды выполнения: 1.8.0_212-release -1586-b04 amd64 VM: виртуальная машина OpenJDK с 64-разрядным сервером от JetBrains sro Windows 8.1 6,3 G C: ParNew, ConcurrentMarkSweep Память: 1237M Ядра: 8 Реестр: ide.new.welcome.screen.force = true Не Подключаемые плагины: org.jetbrains. kotlin, com.google.services.firebase

Я попытался обобщить эту ошибку с помощью приведенного ниже кода, чтобы, надеюсь, сэкономить некоторые усилия, чтобы уловить другой вопрос SO, и я я получаю ту же ошибку компилятора с этим обобщенным кодом.

open class LibraryClassA {

}

open class LibraryClassB {
    val retval = LibraryClassA()

    // this kotlin signature seems to be inferred/transcribed from java by the IDE/compiler
    open fun <T : LibraryClassA?> foobar(): T? {
        return null
    }
}

class MyClass : LibraryClassB() {

    override fun <T : LibraryClassA?> foobar(): T? {
        return retval // compiler error on this line - type mismatch, Required T?, Found LibraryClassA
    }
}

Ответы [ 2 ]

1 голос
/ 30 марта 2020

Вот фундаментальная проблема.

Когда вы пишете

fun <T : LibraryClassA?> foobar(): T? { ... }

, вы заявляете, что абонент из foobar может указать любой подкласс LibraryClassA что они хотят, и получить экземпляр , который . Например, если было

class FooClass : LibraryClassA() { ... }

, кто-то мог бы позвонить

val myFooClass: FooClass = myLibraryClassB.foobar<FooClass>()

и ожидать, что это сработает. То, что у вас есть, будет не работать для этого, потому что у вас будет LibraryClassA экземпляр, не FooClass экземпляр.

Если намерение то, что вы возвращаете некоторый подкласс LibraryClassA?, но реализация LibraryClassB управляет тем, что они получают, а не вызывающим, тогда правильный тип этой функции -

fun foobar(): LibraryClassA? { ... }
0 голосов
/ 03 апреля 2020

Другой ответ объясняет причину ошибки компилятора, но, поскольку я не могу легко изменить библиотеку, которую я использую, решением моей проблемы было выполнение приведения и подавление предупреждения.

Мой финал код выглядит так:

override fun <T : Preference?> findPreference(key: CharSequence): T? {

    // unchecked cast needed since we can't modify the library code to call this with the
    // correct type parameter, and we can't modify the function signature
    @Suppress("UNCHECKED_CAST")
    return this.preference as T
}
...