Типы параметров и возвращаемых значений 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" в целях размывания типа?
Спасибо заранее,
Ал.
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