У меня проблемы при использовании конструктора из-за отсутствия моих знаний 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
Можно ли решить эту проблему или мне нужно найти альтернативный способ без использования дженериков?
Обходной путь состоит в том, чтобы выполнить и 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, в следующий раз мне придется быть осторожным. Спасибо