Рекурсивная общая граница Kotlin с нулевым значением. Как это сделать?

#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))
    }
}