Во-первых, обратите внимание, что KProperty1<T, out R>
имеет параметр типа out
-проецируемого типа R
, поэтому также можно использовать экземпляр KProperty1<Foo, Bar>
, где KProperty1<Foo, Baz>
ожидается, где Baz
является супертипом Bar
, таким как Any
.
Это именно то, что происходит, когда вы вызываете eq
с типами, которые не совсем совпадают: болееОбщий супертип используется для правильного разрешения вызова.
Например, этот вызов:
Person::age eq 1.2f
фактически эквивалентен:
Person::age.eq<Person, Any>(1.2f)
Youможет даже преобразовать его в эту форму, автоматически применяя Заменить инфиксный вызов обычным вызовом , а затем Добавить явные аргументы типа .
Так что всякий раз, когда типыДля точного соответствия общий супертип выбран для R
.В настоящее время нет правильного способа сообщить компилятору, что он не должен возвращаться к супертипу (см. этот вопрос и ответ ).
Последний вызов является побочным эффектом того, как в настоящее время работает вывод типа:кажется, что компилятор должен выбрать одну из перегрузок, прежде чем он решит, совместим ли он для обнуляемости.Если вы замените null
на (null as String?)
, это сработает.Пожалуйста, подайте вопрос для этого на kotl.in / issue .
В общем, желательно не смешивать общие подписи с неуниверсальными из-за возможных общих замен, которые приводят кнеоднозначность.В вашем случае замена R := KProperty1<T, Foo>
(т. Е. Использование eq
для свойства этого типа) приведет к неоднозначности.
Также имеет отношение: