2016-01-08 16 views
24

Piszę program Java, który wykonuje pewne obliczenia na plikach. Program obsługuje 3 rodzaje plików (dokumenty, zdjęcia, filmy) z każdym typem pozwalając tylko kilka formatów:Generowanie 3 wyliczeń w jednym typie

enum DocType { 
    pdf, doc, docx, xls, xlsx, ppt, pptx 
} 

enum ImageType { 
    bmp, jpg, png, gif, ico 
} 

enum VideoType { 
    avi, mpg, mp4, wmv, mov, flv, swf, mkv 
} 

W pewnym momencie w moim programie, chciałbym posiadać rozszerzenie pliku niezależnie od typu pliku oznacza to, że chciałbym móc wykonać jedno z następujących zadań:

FileType fileExt = DocType.doc 
FileType fileExt = ImageType.jpg 
FileType fileExt = VideoType.mp4 

Jak mogę to zrobić w Javie? Wiem, że enum nie może rozszerzyć innych wyliczeń, więc w zasadzie eleganckie rozwiązanie nie jest możliwe.

Dzięki

+4

To może być lepiej zrobić te wyliczenie i śledzić, czy typ pliku jest dokumentem, wideo lub typem obrazu w inny sposób. Być może to wyliczenie będzie miało zmienną instancji innego typu wyliczeniowego, którego członkami są "dokument, obraz, wideo, ...". – user2357112

+2

Punkt styli - wartości 'enum' to' public static final', dlatego powinny być nazwane jak każda inna stała czasu kompilacji - w przypadku 'UPPER_UNDERSCORE'. –

+1

Pozostaję z pytaniem, czy naprawdę potrzebujesz w ogóle wyliczenia. Przy takim użyciu mogę sobie wyobrazić, że lista łańcuchów działałaby dobrze. – jpmc26

Odpowiedz

36

Można zadeklarować interface że reguluje je wszystkie

interface FileType{ 
} 

enum DocType implements FileType{ 
PDF // yes, uppercase for constants 
... 
} 

enum ImageType implements FileType{ 
.... 
} 

a następnie można deklarować zmienne typu FileType

FileType file = DocType.PDF; 
+1

Powiedzmy, że mam "pdf" jako ciąg znaków. Jak przypiszesz go do zmiennej 'fileExt'? (nie wiesz, że pdf to 'DocType') – johni

+3

Nie możesz wykonać tego zadania, ponieważ mają różne typy. Będziesz musiał napisać funkcję, która konwertuje z 'String' na' FileType'. – gardenhead

+1

@johni dodaj metodę 'getFileExt();' do 'interfejsu'. –

23

Możesz umieścić wszystkie rozszerzenia w tym samym enum z polem contentType określającym typ:

enum FileType { 
    PDF(ContentType.DOC), 
    DOC(ContentType.DOC), 
    // other doc types here .. 

    BMP(ContentType.IMAGE), 
    JPG(ContentType.IMAGE), 
    // other image types here .. 

    AVI(ContentType.VIDEO), 
    MPG(ContentType.VIDEO), 
    // other video types here .. 
    ; 

    ContentType contentType; 

    FileType(ContentType contentType){ 
     this.contentType = contentType; 
    } 
} 


enum ContentType{ 
    DOC, IMAGE, VIDEO, 
} 
+1

Rozciąga się to również na czysto, reprezentując nieobsługiwane typy plików, jeśli stanie się to przydatne. Po prostu wpisz 'FileType' zamiast' class' zamiast 'enum' i podaj funkcję fabryczną. –

+0

Jest to również bardziej poprawne rozwiązanie oparte na samouczku Oracle: https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html Możesz również dodać rzeczywisty tekst rozszerzenia pliku do ContentType, aby. toString() wyświetli ".doc" zamiast "DOC". Można również zmienić ten pomysł i typy zawartości zawierają typy plików, w zależności od tego, co jest bardziej odpowiednie w przypadku użycia. – millebi

4

Jedną z rzeczy, które można zrobić, jest posiadanie interfejsu enum o nazwie implements. Oto niektóre przykładowy kod:

Interfejs:

public abstract interface IFileType 
{ 
    public abstract String getExtension(); 
} 

definiowany jako imagetype:

public enum ImageType implements IFileType 
{ 
    BMP("bmp"), 
    JPG("jpg"), 
    PNG("png"), 
    GIF("gif"), 
    ICO("ico"); 

    private String extension; 

    ImageType(String s) 
    { 
     extension= s; 
    } 

    @Override 
    public String getExtension() 
    { 
     return extension; 
    } 
} 

inną definicję jako doctype (tak masz przykład z dwóch rodzajów plików) :

public enum DocType implements IFileType 
{ 
    PDF("pdf"), 
    DOC("doc"), 
    DOCX("docx"), 
    XLS("xls"), 
    XLSX("xlsx"), 
    POWERPOINT("ppt"); 

    private String extension; 

    DocType(String s) 
    { 
     extension= s; 
    } 

    @Override 
    public String getExtension() 
    { 
     return extension; 
    } 
} 

Klasa "Plik" obejmująca rozszerzenie:

public class MyFile 
{ 
    private IFileType fileType; 

    public String getExtension() 
    { 
     return fileType.getExtension(); 
    } 

    public void setType(IFileType t) 
    { 
     fileType = t; 
    } 

    public static void main(String[] args) 
    { 
     MyFile m = new MyFile(); 
     m.setType(ImageType.BMP); 
     System.out.println(m.getExtension()); 
     m.setType(DocType.POWERPOINT); 
     System.out.println(m.getExtension()); 
    } 
} 

Jest to nieco trudny kod, który po prostu spoliczkowałem, aby pokazać kilka rzeczy.

Przede wszystkim chciałem pokazać, w jaki sposób można sprawić, by każde wyrażenie było zgodne z interfejsem, ponieważ uważam, że jest to jeden ze sposobów rozwiązania tego, co próbujesz zrobić. Dzięki temu, że twoje wyliczenia są zgodne z interfejsem, otrzymasz tę miłą gwarancję, że otrzymasz dziedziczenie, że nazwa (funkcje) funkcji są takie same, że zostały zaimplementowane itd.

Kolejna rzecz, którą chciałem pokazać, to: pomysł konstruktora na wyliczenie. Konstruktor w tym przypadku pozwala nam utworzyć odwzorowanie między nazwą wyliczenia (która może być nazwą bardziej czytelną dla człowieka, jak pokazuję z DocType.POWERPOINT) i jej rozszerzeniem. Jestem pewien, że każdy, kto patrzy na kod, wiedziałby, że PPT == powerpoint, ale chciał po prostu wrócić do domu fakt, że nazwa rzeczy może być bardziej opisowa, jeśli zajdzie taka potrzeba. W razie potrzeby możesz dodać dodatkowe parametry do konstruktora, możesz mieć wiele konstruktorów itp.

Jedną ważną rzeczą jest, aby pamiętać, że nie można spróbować stworzyć nowy typ enum spoza samego wyliczenia, tak:

ImageType tiff = new ImageType("tiff"); // 'Cannot instantiate the type ImageType.' 

Nie pójdę do bardziej szczegółowo ponieważ to już wystarczająco długo, ale dobrze, że nie możesz tego zrobić. Konstruktor wyliczenia jest dostępny tylko na liście wartości początkowych (PDF, DOC itp.).

I na koniec, jak wspomina David Z w komentarzu do innej odpowiedzi, możesz mieć MyFile wdrożyć wzór fabryczny - ale zostawiam to jako ćwiczenie dla czytelnika.

Edit:

I oczywiście, jeśli chcesz wiedzieć, jakiego rodzaju typu pliku masz do czynienia z, MyFile może mieć funkcję jak getFileType, lub może mieć szereg funkcji jak isDocType, isImageType itp. Dostarczona wersja MyFile nie jest w zamierzeniu kompletna, po prostu przykładem.