Типы параметров и возвращаемых значений Java для перечисления, реализующего интерфейс



После долгих поисков я нашел много релевантных вопросов к обычным классам, но ни один из них не относится к перечислениям.



Это прекрасно работает:



package list;

public interface Testing {
//treat as a tag interface.
}


package list;

public class Foo implements Testing {
}


package list;

import java.util.ArrayList;
import java.util.List;

public class Bar {
public Bar(){
List<Foo> myList = new ArrayList<Foo>();
myList.add(new Foo());
testList(myList);
testMethod(new Foo());
}

public void testMethod(Testing myInstance){
//do nothing
}

public <Testing> void testList(List<Testing> myList){
//do nothing
}
}


Однако моя проблема заключается в понимании того, что происходит, когда я пытаюсь сделать то же самое с другими людьми.
Enums
вместо
Foo

Пример здесь есть определение интерфейса, которое определяется как принятие параметра интерфейса, который, в действительности, реализуется перечислением, которое реализует интерфейс:



У меня есть два интерфейса:



public interface MyEnumInterface {
//implemented by Enums
}


import java.util.List;

public interface SecondInterface {
public MyEnumInterface testMe(String myString);
public <MyEnumInterface> List<MyEnumInterface> testingList();
public List <MyEnumInterface> enumTestOne(String anotherString);
public List <MyEnumInterface> enumTestTwo(String anotherString);
}


Два эму следующего содержания:



public enum MyEnum implements MyEnumInterface{
VALUE_ONE,
VALUE_TWO,
VALUE_THREE;
}


public enum MyEnum2 implements MyEnumInterface{
VALUE_A,
}


И тестовый класс java:



import java.util.ArrayList;
import java.util.List;

class MyClass implements SecondInterface{

public MyClass(){
single(testMe(""));
enumTestOne("");
enumTestTwo("");
}
public MyEnum testMe(String someParam){
return MyEnum.VALUE_ONE;
}

public List<MyEnumInterface> enumTestOne(String anotherString) {
List<MyEnum> returnL = new ArrayList<MyEnum>();
returnL.add(MyEnum.VALUE_ONE);
returnL.add(MyEnum.VALUE_THREE);
return returnL;
}

public List<MyEnumInterface> enumTestTwo(String anotherString) {
List<MyEnum2> returnL = new ArrayList<MyEnum2>();
returnL.add(MyEnum2.VALUE_A);
return returnL;
}


public List<MyEnum> testingList(){
List<MyEnum> returnL = new ArrayList<MyEnum>();
returnL.add(MyEnum.VALUE_ONE);
returnL.add(MyEnum.VALUE_THREE);
return returnL;
}


public void single(MyEnumInterface val){
System.out.println("Value is " + val);
}


public static void main(String[] args){
MyClass clazz = new MyClass();
}
}


Я борюсь с проблемой, что возвращаемый тип enumTestOne(..) кодируется как список, но интерфейс определяет список. Он прекрасно работает, когда это отдельный экземпляр перечисления "MyEnum", но когда это список значений, он, кажется, терпит неудачу с a:




"ошибка: список методов в классе MyClass не может быть применен к заданный тип;
требуется: список
найдено: список
причина: фактический список аргументов не может быть преобразован в список методом преобразования вызова "




Я не уверен, как это обойти - я попытался добавить объявление, которое вы видите выше, чтобы оно гласило:
public <MyEnumInterface> List<MyEnumInterface> testingList();
но это тогда дает мне "предупреждения" о непроверенных бросках, продолжая терпеть неудачу



Все это происходит из-за моего отсутствия более глубокого понимания дженериков и того, как они соотносятся с перечислениями.

Я видел кое-что интересное. заявления в отношении
<? extends Enum<E> & SecondInterface>
но это расширяет мое понимание. Пожалуйста, помогите!



В качестве отступления, правильно ли я думаю, что объявления gerneic перед возвращаемым классом используются для указания "T" в целях размывания типа?



Спасибо заранее,



Ал.

617   2  

2 ответов:

Если вы хотите разрешить реализующему классу определять, какую реализацию MyEnumInterface Использовать, вы можете указать возвращаемый тип методов интерфейса как List любого MyEnumInterface.

public List<? extends MyEnumInterface> enumTestOne(String anotherString);
public List<? extends MyEnumInterface> enumTestTwo(String anotherString);

Реализации этих методов могут затем определить конкретный тип возвращаемого значения.

public List<MyEnum> enumTestOne(String anotherString) {
    List<MyEnum> returnL = new ArrayList<MyEnum>();
    returnL.add(MyEnum.VALUE_ONE);
    returnL.add(MyEnum.VALUE_THREE);
    return returnL;
}

public List<MyEnum2> enumTestTwo(String anotherString) {
    List<MyEnum2> returnL = new ArrayList<MyEnum2>();
    returnL.add(MyEnum2.VALUE_A);
    return returnL;
}
Кстати, вы можете сделать то же самое в" обратном порядке " с super. Это указывает, что может использоваться любой тип, являющийся супертипом данного типа.
public void addToList(List<? super MyEnum> list) {
    list.add(MyEnum.VALUE_ONE);
}

addToList(new ArrayList<MyEnum>());
addToList(new ArrayList<MyEnumInterface>());

См. также

Java Универсальные Символы (Подстановочные Знаки)

Почему класс SomeClass не эквивалентен классу SomeClass в универсальных типах Java?

Дженерики являются invariant в природе. Так что List<String> не является подтипом List<Object>

Вам придется изменить свой метод, чтобы включить список MyEnumInterface, а не отдельные классы перечисления.

public List<MyEnumInterface> enumTestOne(String anotherString) {
    List<MyEnumInterface> returnL = new ArrayList<MyEnumInterface>();//Change
    returnL.add(MyEnum.VALUE_ONE);
    returnL.add(MyEnum.VALUE_THREE);
    return returnL;
}

public List<MyEnumInterface> enumTestTwo(String anotherString) {
    List<MyEnumInterface> returnL = new ArrayList<MyEnumInterface>();//Change
    returnL.add(MyEnum2.VALUE_A);
    return returnL;
}

Comments

    Ничего не найдено.