#kotlin #generics #recursion #nullable
#kotlin #общие #рекурсия #обнуляемый
Вопрос:
Я столкнулся с проблемой, пытаясь объединить 3 концепции вместе в Kotlin: дженерики, дженерики с рекурсивной границей, обнуляемая общая граница. Вот код:
class ClassA<T>(val field: T)
val OBJ1 = ClassA("1")
val OBJ2 = ClassA<String?>(null)
val OBJ3 = ClassA<String?>("3")
class ClassB<T: Comparable<T>>(val field: ClassA<T>) {
companion object {
val VALUES: Set<ClassB<*>> = setOf(ClassB(OBJ1), ClassB(OBJ2), ClassB(OBJ3))
}
}
Выражения ClassB(OBJ2)
и ClassB(OBJ3)
не могут быть скомпилированы, потому что String? isn't a subtype of Comparable<String?>
Кто-нибудь знает обходной путь для этой проблемы? Я пробовал T: Comparable<T?>
, T: Comparable<T>?
, T: Comparable<T?>?
. Ни один из них не сработал для меня.
Спасибо.
Комментарии:
1. Мне кажется, что просто использование nullable типа в качестве верхней границы работает :
T: Comparable<T>?
.2. @горячая клавиша Я попробовал. Не работает. Все еще вижу ошибку времени компиляции в Idea.
3. Это невозможно, поскольку вы не можете просто сравнить a
String
сnull
. Например"foo" < null
, недопустимо. Если вы объясните немного больше, чего вы хотели бы достичь, мы могли бы предложить альтернативные решения. Из текущего примера это неясно.
Ответ №1:
Прежде всего, верхняя граница T
должна быть обнуляемой T
, чтобы быть обнуляемой.
class ClassB<T: Comparable<T>?>(val field: ClassA<T>)
Я думаю String?
, что это не подтип Comparable<String?>?
, потому String
что сам по себе не является подтипом Comparable<String?>
. Я не знаю, как это обойти. Вот как они определили класс String, чтобы вы не могли его изменить.
Если вы создаете класс-оболочку String, он работает:
class ClassA<T>(val field: T)
class String2(val value: String): Comparable<String2?> {
override fun compareTo(other: String2?): Int {
other ?: return 1
return value.compareTo(other.x)
}
}
val OBJ1 = ClassA(String2("1"))
val OBJ2 = ClassA<String2?>(null)
val OBJ3 = ClassA<String2?>(String2("3"))
class ClassB<T: Comparable<T>?>(val field: ClassA<T>) {
companion object {
val VALUES: Set<ClassB<*>> = setOf(ClassB(OBJ1), ClassB(OBJ2), ClassB(OBJ3))
}
}