Это из-за перегрузки конфликтов.
Эффективно, с вашими текущими параметрами, T
может быть равно U
. Если вы знакомы с перегрузкой, вы должны знать, что это запрещено:
fun something(x: Int){ /* foo */ }
fun something(x: Int){ /* bar */ }
Но для примера это:
fun something(x: Int){ /* foo */ }
fun something(x: Float){ /* bar */ }
Поскольку они потенциально могут быть одинаковыми, это может привести к конфликтам. Как он узнает, какой метод вызывать?
При полном диапазоне компилятор будет жаловаться. Если вы используете : SomeClass
для одного аргумента, он перестанет жаловаться. Но вот случайный пример:
class MapBuilder<T, U : Logger> {
operator fun invoke(arg: T): MapBuilder<T, U> {
return this
}
operator fun invoke(arg: U): MapBuilder<T, U> {
return this
}
}
fun t(){
MapBuilder<Logger, Logger>().invoke(LoggerFactory.getLogger(""))
}
invoke
будет неоднозначным. Проблема теперь существует, только если у вас есть два одинаковых типа; что он использует?
Теперь ваш MCVE чрезвычайно минимален. Я не знаю, для чего вы используете T и U. В результате я не могу дать вам примеры кода. Но вот что вам нужно знать:
Вы не можете иметь два из этих методов с любыми типами, потому что они могут конфликтовать. Даже использование дисперсии вызовет проблемы с перегрузкой, если вы используете два одинаковых типа. Так что это исключило бы MapBuilder<Int, Int>
для экземпляра.
Вы можете использовать один метод или разделить их на два метода с разными именами. Название показывает, что это строитель, поэтому вы можете иметь withKey(T t)
и withValue(U u)
Нет способа запретить T == U напрямую, не пройдя Class<T>
и Class<U>
и не проверив их. К сожалению, компилятор не понимает этого даже с require
или другими контрактными функциями. Кроме того, прежде чем вы попробуете это, использование : Any
не работает. Это ограничение по умолчанию. Помните, что в Java все равно Object
, а в Котлине Any
.
Вы можете обойти это с помощью @JvmName (упомянуто в ответе Jayson Minard ), но вы будете использовать два разных имени метода, если будете взаимодействовать с Java. Это может быть немного проще, если вы используете только Kotlin. Взаимодействие Java-Kotlin имеет множество @Jvm*
аннотаций, большинство / все из которых покрыты в документах .
Даже с @JvmName все равно будет разрешено <String, String>
, пока не будет вызван конфликтующий метод. Если вы хотите утверждать T! = U, несмотря ни на что, вам нужно запустить проверку классов.