2014-01-20 3 views
0

Давайте предположим, что у меня есть перечисление: Реализовать интерфейс со значением перечисления в качестве родового параметра

enum Resource { FILE, URL, STREAM } 

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

interface Reader<R extends Resource> 

Можно ли создавать различные реализации его использования с помощью членов Enum? Как что:

class FileReader implements Reader<Resource.FILE> 

Мои язь основные моменты этого текста с красным (который не является большой неожиданностью).

+2

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

ответ

1

Как уже упоминалось Александр Токарев, вы не можете сделать это. Альтернатива его подход состоит в том, чтобы свернуть свои собственные перечислений подобных классов, расширяя вложенные классы от базового класса, который имеет частный конструктор:

public class Resource { 
    private Resource() {} 

    // some methods, abstract methods, etc... 

    public static class File extends Resource { 
     private File() {} 

     // etc... 
    } 

    private static final File FILE = new File(); 

    // other subclasses of Resource 
} 

Теперь вы можете использовать дженерик, как обычно:

interface Reader<R extends Resource> {...} 
class FileReader implements Reader<Resource.File> {...} 

Это дает вам много преимуществ, которые перечислены как: безопасность типа, закрытый набор значений и т. Д. - при явной настройке иерархии классов, которую вы можете использовать с дженериками. Основная стоимость заключается в краткости кода, хотя вы также теряете возможность использовать значения в операторах switch, а также некоторые другие, более эзотерические преимущества перечислений.

2

Участниками перечисления являются экземпляры типа enum, а не подклассы. Более того, перечисления не могут быть подклассами. Таким образом, вы не можете скомпилировать свой код.

Я предлагаю вам написать так:

interface Reader { 
    Resource getResource() 
    .... 
} 

class FileReader implements Reader { 
    @Override 
    public Resource getResource() {return Resource.FILE;} 
    ... 
} 
+1

Члены перечисления могут фактически быть подклассами типа перечисления, если они объявляют тело класса (т. Е. Если за именем enum следуют фигурные скобки). Но этот расширенный класс является анонимным классом и, как таковой, не имеет имени и не может ссылаться в общем объявлении. См. [JLS 8.9.1] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.1). – yshavit

Смежные вопросы