Есть ли способ объявить T в конструкторе в Котлине?

У меня проблемы при использовании конструктора из-за отсутствия моих знаний Kotlin. Я искал и искал, но то, что я мог получить, это только использование дженериков в методах или классах.

Я использую как классы Java, так и классы Kotlin. Я приведу вам пример

class A<T extends Enum<T> & A.Type<T>> {
    interface Type<T extends Enum<T> & Type<T>> {
        String getData();
    }

    public enum Example implements Type<Example> {
        HELLO("data1"),
        WORLD("data2");

        public Example(String data) {
            this.data = data;
        }

        private final String data;

        @Override
        public String getData() {
            return data;
        }
    }

    public enum Example2 implements Type<Example2> {
        BYE("1Data"),
        WORLD("2Data");

        public Example2(String data) {
            this.data = data;
        }

        private final String data;

        @Override
        public String getData() {
            return data;
        }
    }

    //And there are several enum classes

    public final T[] types;

    public A(T[] type) {
        types = type;
    }

    public String get(T t) {
        for(int i = 0; i < types.length; i++) {
            if (types[i] == t) {
                return types[i].getData();
            }
        }
        return "";
    }
}

Не знаю, как правильно использовать этот класс, потому что я сделал это, пока пишу этот вопрос, но основная структура такая. То, что я действительно использую, является более сложной вещью (не сделано мной), поэтому объяснение проблемы, с которой я сталкиваюсь, будет лучше с этим классом. Так что я смогу инициализировать класс A, вызвав что-то вроде new A(A.Example.values());

Теперь давайте предположим, что я хочу использовать этот A в качестве параметра в конструкторе класса с именем B

class B {
    var data: String = ""

    val a: A<*>

    constructor(a: A<*>) {
        this.a = a
        this.data = a.get(a.types[0]) //This is the problem
    }
}

Всякий раз, когда я пытаюсь установить data, вызывая a.get(a.types[0]) для данных по умолчанию, Kotlin вызывает проблему, потому что a.get() требует Nothing, а a.types[0] есть Enum<*>

Я думаю, что смогу исправить это, указав * как что-то, но я не могу понять правильные дженерики... Объявление T, чтобы указать, что T расширяет Enum и реализует Type, будет так, как я думаю. Метод можно сделать подобным образом, но я не смог в конструкторе. Поставить Any вместо * тоже не сработало, потому что написано Any не распространяется Enum

Можно ли решить эту проблему или мне нужно найти альтернативный способ без использования дженериков?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
87
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Обходной путь состоит в том, чтобы выполнить и get, и types в одной операции, чтобы компилятор знал, что типы совпадают. Я думаю, что метод расширения должен работать так же, как и метод, объявленный внутри A:

fun <T> A<T>.getByIndex(i: Int) where T: A.Type<T>, T: Enum<T> = get(types[i])

// in B's constructor
this.data = a.getByIndex(0)

Я предполагаю, что A<T>.get возвращает String, поэтому код в B имеет смысл; если это зависит от T, у вас все еще есть проблемы.

Ах, извините, я видел, что мой код был неправильным. Да, A.get() должен возвращать types[i].getData() или возвращает пустую строку. Думаю твой способ сработает. Я заметил, что это кажется нормальным как для Java, так и для Kotlin, в следующий раз мне придется быть осторожным. Спасибо

Mandarin Smell 22.12.2020 05:50

Другие вопросы по теме