Domanda Come definire le proprietà per gli oggetti Enum


Ho letto la domanda Differenza di Enum tra java e C ++? ma sono ancora confuso.

Vorrei quanto segue per restituire la stringa correlata:

public enum Checker {
    EMPTY ("Empty"),
    RED ("Red"),
    YELLOW ("Yellow");
}

Da quello che ho letto, questo dovrebbe essere possibile. Vorrei solo che tu facessi luce su come implementarlo.


44
2018-06-16 14:33


origine


risposte:


Risposta breve

Hai bisogno di un costruttore, un campo e un getter.

Costruttori

I tipi Enum possono avere costruttori, a condizione che il loro livello di accesso sia privato o predefinito (pacchetto-privato). Non è possibile chiamare direttamente questi costruttori, tranne nella dichiarazione enum stessa. Simile alle classi, quando si definisce una costante enum senza parametri, si chiama effettivamente il costruttore predefinito generato dal compilatore. Per esempio.

public enum King{
    ELVIS
}

è equivalente a

public enum King{
    ELVIS() // the compiler will happily accept this
}

E proprio come nelle classi, se si definisce un costruttore esplicito, il compilatore non inserirà un costruttore predefinito, quindi non verrà compilato:

public enum King{
    ELVIS, // error, default constructor is not defined
    MICHAEL_JACKSON(true)
    ;
    private boolean kingOfPop;
    King(boolean kingOfPop){this.kingOfPop = kingOfPop;}
}

Questo è un buon riferimento alle enumerazioni questo spiega anche i problemi del costruttore.

Campi e accessori

Le enumerazioni sono costanti e sono immutabili in quanto tali. Possono tuttavia definire campi, che possono avere uno stato. Questa è una pratica terribile, perché gli sviluppatori si aspettano che le enumerazioni e i valori associati siano costanti, ma tu può Definisci ancora un campo non finale in un enum con getter e setter.

Questo è un codice java legale:

public enum Color{
    RED("FF0000"),
    GREEN("00FF00"),
    BLUE("0000FF");
    private String code;
    public String getCode(){return code;}
    public void setCode(String code){this.code = code;}
    private Color(String code){this.code = code;}
}

Ma abilita codice malvagio come questo:

String oldBlue = Color.BLUE.getCode();
Color.BLUE.setCode(Color.RED.getCode());
Color.RED.setCode(oldBlue);

Quindi nel 99,99% dei casi: se hai dei campi nella tua enumerazione, dovresti renderli definitivi e fornire solo i getter. Se i campi non sono immutabili, fornire copie difensive:

public enum Band{
    THE_BEATLES("John","Paul","George","Ringo");
    private final List<String> members;
    public List<String> getMembers(){
        // defensive copy, because the original list is mutable
        return new ArrayList<String>(members);
    }
    private Band(String... members){
        this.members=Arrays.asList(members);
    }
}

Soluzione

Nel tuo caso è molto semplice: hai solo bisogno di un singolo campo di tipo string (immutabile), quindi inizializzarlo nel costruttore e fornire un getter è perfettamente ok:

public enum Checker {

    EMPTY ("Empty"),
    RED ("Red"),
    YELLOW ("Yellow");

    private final String value;

    private Checker(final String value) {
        this.value = value;
    }

    public String getValue() { return value; }
}

90
2018-06-16 14:36



Se il modello regge, funziona anche così ed elimina la ripetizione:

public enum Checker {
    EMPTY,
    RED,
    YELLOW;


    public String getDescription(){
        String name = name();
        return ""+Character.toUpperCase(name.charAt(0))
                 +name.substring(1).toLowerCase();
    }

}

6
2018-06-16 14:44