2016-02-26 9 views
16

Sto scrivendo una libreria, che ha un insieme predefinito di valori per un enum. Diciamo che il mio enum appare come sotto.Come abilitare l'ereditarietà dell'enum

public enum EnumClass { 
    FIRST("first"), 
    SECOND("second"), 
    THIRD("third"); 

    private String httpMethodType; 

} 

Ora il client che sta utilizzando questa libreria potrebbe dover aggiungere alcuni altri valori. Diciamo che il cliente deve aggiungere CUSTOM_FIRST e CUSTOM_SECOND. Questo non sovrascrive alcun valore esistente, ma rende l'enumerazione con 5 valori.

Dopo questo, dovrei essere in grado di utilizzare qualcosa come <? extends EnumClass> per avere 5 possibilità costanti.

Quale sarebbe l'approccio migliore per raggiungere questo obiettivo?

+1

questo sarà utile http://stackoverflow.com/a/478431/3138755 – Rahul

+1

Le enumerazioni sono buone quando si è certi del numero di valori possibili noti a priori.Se ti aspetti che venga esteso, probabilmente non dovresti mai usare le enumerazioni, e rivedere l'argomento per cui è progettata l'enumerazione attuale e probabilmente lasciarlo in favore delle classi che implementano un'interfaccia ben progettata. –

risposta

20

Non è possibile avere un enum estendere un altro enum e non è possibile "aggiungere" valori a uno esistente enum tramite ereditarietà.

Tuttavia, enum s può implementare interface s.

Quello che vorrei fare è avere l'originale enum implementare un marcatore interface (vale a dire senza dichiarazioni di metodo), allora il vostro cliente potrebbe creare la propria enum attuazione della stessa interface.

Quindi i valori enum saranno indicati dal loro comune interface.

Al fine di rafforzare i requisiti, è possibile che l'interfaccia dichiari metodi pertinenti, ad es. nel tuo caso, qualcosa nelle linee di public String getHTTPMethodType();.

Ciò imporrebbe l'implementazione di enum s per fornire un'implementazione per tale metodo.

Questa impostazione accoppiato con una documentazione API adeguata dovrebbe contribuire ad aggiungere funzionalità in modo relativamente controllato.

autonomo esempio (non mente i nomi pigri qui)

package test; 

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

public class Main { 

    public static void main(String[] args) { 
     List<HTTPMethodConvertible> blah = new ArrayList<>(); 
     blah.add(LibraryEnum.FIRST); 
     blah.add(ClientEnum.BLABLABLA); 
     for (HTTPMethodConvertible element: blah) { 
      System.out.println(element.getHTTPMethodType()); 
     } 
    } 

    static interface HTTPMethodConvertible { 
     public String getHTTPMethodType(); 
    } 
    static enum LibraryEnum implements HTTPMethodConvertible { 
     FIRST("first"), 
     SECOND("second"), 
     THIRD("third"); 
     String httpMethodType; 
     LibraryEnum(String s) { 
      httpMethodType = s; 
     } 
     public String getHTTPMethodType() { 
      return httpMethodType; 
     } 
    } 
    static enum ClientEnum implements HTTPMethodConvertible { 
     FOO("GET"),BAR("PUT"),BLAH("OPTIONS"),MEH("DELETE"),BLABLABLA("POST"); 
     String httpMethodType; 
     ClientEnum(String s){ 
      httpMethodType = s; 
     } 
     public String getHTTPMethodType() { 
      return httpMethodType; 
     } 
    } 
} 

uscita

first 
POST 
+0

Mi è piaciuto questo approccio. Tuttavia, una query. Di solito mentre usiamo enum nel codice per usarlo come valore predefinito (una costante da una lista data), usiamo qualcosa come "LibraryEnum.FIRST'. Come suggeriresti di usare quando è via interfaccia? –

+0

@KiranAB puoi dichiarare/implementare un metodo 'getDefaultValue', restituendo il tipo' dell'interfaccia'. In questo modo ogni 'enum' dovrà implementarlo e restituire un valore predefinito (o' null'). – Mena

+0

Un'altra domanda. Ho aggiunto un metodo, che funziona in modo simile a valueOf. Ora come faccio ad avere accesso statico, perché l'interfaccia non può avere metodi statici. E se non lo aggiungo nell'interfaccia, come faccio a imporre al client di implementare tale metodo .. –

3

Enums non sono estensibili. Per risolvere il problema è sufficiente

  • girare l'enum in una classe
  • creare le costanti per i tipi predefiniti
  • se si desidera un sostituto per Enum.valueOf: tenere traccia di tutte le istanze della classe in una mappa statica

Ad esempio:

public class MyType { 
    private static final HashMap<String,MyType> map = new HashMap<>(); 
    private String name; 
    private String httpMethodType; 

    // replacement for Enum.valueOf 
    public static MyType valueOf(String name) { 
     return map.get(name); 
    } 

    public MyType(String name, String httpMethodType) { 
     this.name = name; 
     this.httpMethodType = httpMethodType; 
     map.put(name, this); 
    } 

    // accessors 
    public String name() { return name; } 
    public String httpMethodType() { return httpMethodType; } 

    // predefined constants 
    public static final MyType FIRST = new MyType("FIRST", "first"); 
    public static final MyType SECOND = new MyType("SECOND", "second"); 
    ... 
} 
+0

Questo è quello che avevo in mente. Sono abbastanza nuovo di java (ho iniziato a usarlo circa 40 giorni fa), quindi non potrei dire se questo è il costrutto giusto. È solo che sembra leggermente confuso. Consiglieresti di pulirlo un po '? –

+1

cosa trovi disordinato? – wero