Kotlin универсальный параметр функции c несоответствие типов типов - PullRequest
0 голосов
/ 29 января 2020

У меня есть логи c, похожие на описанные ниже. Может кто-нибудь объяснить мне, почему выполнение fB() показывает несоответствие?

interface SomeInterface<T> {
    fun showMe(aa: T)
    fun getOne(): T
}
interface Jsonizer {
    //something here
}
data class Template (val id: String): Jsonizer
object SomeImpl: SomeInterface<Template> {
    override fun showMe(aa: Template) {
        println("It $aa")
    }

    override fun getOne(): Template {
        return Template("91919191")
    }
}

fun fA() {
     // ERROR:
     // Required: SomeInterface<Jsonizer>
     // Found: SomeImpl
     fB(SomeImpl)
}

fun fB(service: SomeInterface<Jsonizer>) {
     val tmp1 = Template("112233") // assume it's generate by jsonizer
     service.showMe(tmp1)
     val tm2 = service.getOne()
}

Ответы [ 2 ]

0 голосов
/ 29 января 2020
  • SomeImpl реализует SomeInterface<Template>
  • fun fB потребностей SomeInterface<Jsonizer>

Если вы хотите, чтобы fB работал, вы можете добавить введите для функции:

fun <T> fB(service: SomeInterface<T>)

0 голосов
/ 29 января 2020

Функция fB требует SomeInterface<Jsonizer> или один из ее подтипов. SomeImpl является подтипом SomeInterface<Template>, а SomeInterface является инвариантом по своему параметру generi c, поэтому SomeInterface<Template> НЕ является подтипом SomeInterface<Jsonizer>, хотя Template реализует Jsonizer.

Если вы хотите, чтобы SomeInterface<Template> был подтипом SomeInterface<Jsonizer>, вы должны сделать SomeInterface ковариантным, но это невозможно, потому что методы в ковариантном классе не могут получить экземпляр этого родового c введите в качестве параметра, и у вас есть метод showMe, который принимает T в качестве параметра.

Все это означает, что вам следует перепроектировать архитектуру вашего класса. Например, вы можете разделить ваш SomeInterface на интерфейсы потребителя и производителя - потребителя с методом showMe и производителя с методом getOne, чтобы вы могли сделать производителя ковариантным и потребителем контравариантным и создать различные реализации для конкретных подтипов Jsonizer как вы пытаетесь в своем коде.

...