Intereting Posts
Соответствие регулярных выражений в строке Как вернуться из функции функции Котлина Библиотека Kotlin 'classes.jar' имеет неподдерживаемый формат. Обновите библиотеку или плагин Все возможные комбинации из двух списков Котлинское отношение реляционного равенства на Int со значениями от -128 до 127 Могу ли я интегрировать и использовать рекламные объявления admob в проекте Android с помощью Kotlin? Джексон-десериализация – классы данных Kotlin – значения по умолчанию для отсутствующих полей на картографе указать класс Kotlin как точку входа Main-Class в MANIFEST.MF? RxJava2 Может быть возвращено пустое Наблюдаемое, если ни один элемент Применение перечисления состоит из 3 адаптеров между 2 действиями в Котлине Динамический бросок в Котлине Как превратить Mutable Collection в неизменяемую Фрагмент: RelativeLayout Видимость не изменяется в OnCreateView Как смешивать ScatterChart с горизонтальными и вертикальными линиями Функция Котлина: Требуемая единица измерения? Найдено Int

Функции расширения для общих классов в Котлине

Что случилось с моей функцией расширения ниже

class Foo<T> { fun <T> Foo<T>.plus(that: Foo<T>): Foo<T> = throw Exception() init { Foo<Int>() + Foo<String>() // A receiver of type Foo<T> is required } } 

Обновить

Интересно, почему это отличается от регулярных функций расширения, где T успешно выводится как Any и хочет достичь такого же поведения, например T, чтобы получить вывод как Foo <Any>

 class Foo { fun <T> T.foo(that: T): T = throw Exception() init { "str" foo 42 } } 

Проблема заключается в том, как работают дженерики.

 class Foo { fun <T> T.foo(that: T): T = throw Exception() init { "str" foo 42 } } 

Это работает, потому что компилятор может найти T который соответствует как сигнатуре функции, так и аргументам: это Any , и функция превращается в эту:

 fun Any.foo(that: Any): Any = ... 

Теперь String является подтипом Any , Int является подтипом Any , поэтому эта функция применима к аргументам.

Но в вашем первом примере:

 class Foo<T> { fun <T> Foo<T>.plus(that: Foo<T>): Foo<T> = throw Exception() init { Foo<Int>() + Foo<String>() // A receiver of type Foo<T> is required } } 

Все по-другому. Такого T . Давайте будем наивными и попробуем Any :

 fun Foo<Any>.plus(that: Foo<Any>): Foo<Any> = ... 

Теперь Foo инвариантен в T , поэтому Foo<Int> не является подтипом Foo<Any> , и на самом деле нет типа T кроме Int что сделало бы Foo<T> супертипом Foo<Int> . Итак, T должен быть точно Int , но он также должен быть точно String по той же логике (из-за второго аргумента), поэтому нет решения, и функция не применима.

Вы можете заставить его работать, сделав совместный вариант Foo в T :

 class Foo<out T> { fun <T> Foo<T>.plus(that: Foo<T>): Foo<T> = throw Exception() init { Foo<Int>() + Foo<String>() // A receiver of type Foo<T> is required } } 

Это накладывает некоторые ограничения на возможные подписи членов Foo , но если вы в порядке с ними, это исправляет вашу проблему.

Посмотрите на эту ссылку для получения дополнительной информации: http://kotlinlang.org/docs/reference/generics.html

Ваш метод plus ожидает, что параметр будет иметь тот же общий тип параметра T что и приемник. Следовательно, вы не можете добавить Foo<String> в Foo<Int> .

Если вы хотите добавить все типы Foo , вам нужно объявить свою функцию расширения следующим образом:

 operator fun <T,R> Foo<T>.plus(that: Foo<R>): Foo<T> = throw Exception()