EnumSet как параметр в интерфейсе generi c - PullRequest
1 голос
/ 10 марта 2020

У меня есть вариант использования:

inteface A{
  get(EnumSet<?> fetchModes);
}
class B implements A{

  //Here FetchMode is an enum
  get(EnumSet<FetchMode> fetchMode){
   //Some logic here
  }
}

Но он выдает ошибку времени компиляции:

Метод get класса B имеет такое же стирание, что и get (EnumSet fetchMode) типа A, но не переопределяет его.

Я читал, что Enums не может быть обобщенным c, но есть ли способ реализовать этот сценарий использования? (По сути, нужно, чтобы EnumSet был обобщенным c, и разные реализации могут передавать разные Enums)

Ответы [ 2 ]

6 голосов
/ 10 марта 2020

Метод может переопределить другой, если типы аргументов точно совпадают, а ваш - нет. Даже если EnumSet<FetchMode> является подтипом EnumSet<?>, они не совсем одинаковы. Вы не переопределяете метод суперкласса get(EnumSet<?> fetchModes); в своем подклассе, скорее вы перегружаете его другим типом параметра. Оба из них имеют одинаковую подпись из-за стирания, когда вы проверяете или декомпилируете байт-код get(EnumSet fetchModes), и ваш компилятор начинает жаловаться.

Это описано в JLS §8.4.8.1 :

В классе не может быть двух методов-членов с одинаковым именем и стиранием типа

Наивной попыткой решения проблемы является изменение типа параметра таким образом, чтобы он был совместим с типом суперкласса, должным образом переопределяя метод в вашем подклассе.

@Override
public void get(EnumSet<?> fetchModes) {

}

Хотя это исправляет ошибка компилятора после моды, она все еще не элегантна, поскольку она позволяет вашему EnumSet хранить любой объект. Но в идеале вы можете захотеть хранить только некоторый подтип Enum. Эта идиома поддерживает это.

Что вам нужно сделать, это объявить обобщенный интерфейс c с параметром ограниченного типа, а затем реализовать его путем правильной переопределения метода, как показано ниже.

public interface A<E extends Enum<E>> {
    void get(EnumSet<E> fetchModes);
}

public class B implements A<FetchMode> {
    @Override
    public void get(EnumSet<FetchMode> fetchModes) {

    }
}
4 голосов
/ 10 марта 2020

попробуйте это сделать, чтобы тип c тип расширяет Enum:

public class B implements A<FetchMode> {
    //Here FetchMode is an enum
    public void get(EnumSet<FetchMode> fetchMode){
        //Some logic here
    }
}
}

interface A<T extends Enum<T>> {
    void get(EnumSet<T> fetchModes);
}
...