Параметры типа Котлина с верхними границами - PullRequest
0 голосов
/ 12 июня 2018

Я ожидаю, что следующее вызовет ошибку компиляции, но это не так.Любые идеи, почему?

fun <T, U: T> foo(a: T, b: U) {
    println("$a $b")
}

foo("bar", 123)

Если я вызываю foo() с явными аргументами типа, он не может скомпилировать, как ожидалось:

foo<String, Int>("bar", 123)
Error: Kotlin: Type argument is not within its bounds: should be subtype of 'String'

Ответы [ 3 ]

0 голосов
/ 12 июня 2018

Компилятор изо всех сил старается подогнать параметры, которые вы указали в сигнатуре функции.В этом случае он выводит параметры типа Any и Int, поэтому он в основном вызывает функцию, подобную этой, что, конечно, удовлетворяет требованию верхней границы, потому что Any является супертипом Int:

foo<Any, Int>("bar", 123)

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

  1. Вы можете открыть намеренные действия ( Alt + Enter в Windows, 101 в macOS), когда курсор находится на вызове функции foo и выберите Add explicit type arguments.Это создаст строку выше.

  2. Вы можете сделать функцию reified и распечатать классы параметров типа - это будут те параметры, о которых она знаетво время компиляции.

    inline fun <reified T, reified U: T> foo(a: T, b: U) {
        println("$a $b")
        println(T::class) // class kotlin.Any
        println(U::class) // class kotlin.Int
    }
    
0 голосов
/ 12 июня 2018

В первом случае компилятор не знает, какой тип вы подразумеваете под T, поэтому он должен угадать и не обязательно угадать тип самый строгий .Одно из предположений о языках, которые используют вывод типов, состоит в том, что программист имел в виду что-то правильное.String и Int оба являются потомками типа Any, поэтому компилятор может разрешить первый вызов, подставив Any вместо T.Следовательно, ошибки нет.

Как только вы определите типы, компилятор получит лучшее представление о том, что вы хотите, и в этом случае это ошибка.Но первый случай верен.

0 голосов
/ 12 июня 2018

Вывод типа пытается найти подходящую пару.В этом случае это будет явный

foo<Any, Int>("bar", 123)

Компилятору известно соотношение T и U, и поэтому ему просто нужно найти общий супер тип для String и Int для T.

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