Причина, почему вывод типа не удалось в Kotlin - PullRequest
0 голосов
/ 05 марта 2019


Может кто-нибудь помочь мне разобраться с поведением компилятора Kotlin?
Цель программы - преобразовать входную строку в соответствующий тип (BMsg или CMsg) и напечататьрезультат в консоли.
Однако я получаю следующее сообщение от компилятора:

"Ошибка вывода типа. Недостаточно информации для вывода параметра T ..."

import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper

abstract class classA<T> {
    fun handle(body: String) {
        val result = convertToSpecificMessageType(body) // This line fails
        printResult(result)
        otherImportantStuff()
    }

    abstract fun otherImportantStuff()

    private inline fun <reified T : Any> String.toPayloadObject(): T =
            jacksonObjectMapper().readValue(this, T::class.java)

    private inline fun  <reified T : Any> convertToSpecificMessageType(body: String): T = body.toPayloadObject()
    private fun printResult(result: T) = println("result = $result")
}

class classB : classA<BMsg>() {
    override fun otherImportantStuff() = print("important stuff of class B")
}

class classC : classA<CMsg>() {
    override fun otherImportantStuff() = print("important stuff of class C")
}

sealed class Msg
data class BMsg(val x: String) : Msg()
data class CMsg(val y: Int) : Msg()

fun main() {
    classB().handle("{\"x\" : \"aaa\"}")
    classC().handle("{\"y\" : 5}")
}    

Несмотря на то, что я нашел обходной путь - объявление метода convertToSpecificMessageType как abstract и переопределение в classB / classC, мне интересно (1), по какой причине компиляторпожаловаться (2), если есть способ исправить проблему, не переопределяя convertToSpecificMessageType?Заранее спасибо!

PS kotlin version = '1.3.21'

1 Ответ

0 голосов
/ 05 марта 2019

Объявляя <reified T : Any> перед вашими методами (toPayloadObject и convertToSpecificMessageType), вы вводите новый параметр типа T для ваших методов, который не имеет отношения к параметру типа classA с помощьюто же имя T.

Объявление локального метода T shadows T on classA.

В результате при выполненииval result = convertToSpecificMessageType(body) - нет никакого контекста, который Котлин может использовать для вывода типа.Хотя вы находитесь в методе classA, T из класса A не используется методом convertToSpecificMessageType.

Решение?

Нельзя использовать тип reifiedдля класса:

  • вы можете удалить части <reified T : Any> и передать объект класса методам
  • или оставить его там, но вы предоставляете контекст при вызовеметод как в val result = convertToSpecificMessageType<MyType>(body) или val result : MyType = convertToSpecificMessageType(body)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...