Un'altra opzione sarebbe quella di usare un secondo enum e un costruttore di varargs insieme a un EnumSet
:
enum JavaType {
INTEGER(TypeProperty.PRIMITIVE, TypeProperty.NUMERIC),
BOOLEAN(TypeProperty.PRIMITIVE),
STRING(),
/* ... */;
private EnumSet<TypeProperty> properties;
private JavaType(TypeProperty... properties) {
this.properties = EnumSet.copyOf(Arrays.asList(properties));
}
public boolean isPrimitive() {
return properties.contains(TypeProperty.PRIMITIVE);
}
public boolean isNumeric() {
return properties.contains(TypeProperty.NUMERIC);
}
/* ... */
private enum TypeProperty {
PRIMITIVE,
NUMERIC,
/* ... */
}
}
Questo ha il vantaggio di non richiedere di specificare un gruppo di valori falsi in un costruttore (il problema con # 2), ma non richiede un gruppo di classi interne per ogni enumerazione. Il TypeProperty
enum non ha nemmeno bisogno di essere visibile al di fuori di JavaType
perché funzioni.
In alternativa, TypeProperty
può essere reso pubblico e può esserci un metodo is(TypeProperty)
. Che tu lo voglia o no dipende da come prevedi di utilizzare JavaType
; può essere conveniente esporlo (ad es. per creare un metodo allWith(TypeProperty)
) ma se non è qualcosa che potresti usare all'esterno, non esporlo. Che lo vogliate o meno dipende da come userete il vostro enum.
Se viene visualizzato TypeProperty
, potrebbe essere combinato con un importazione statica in modo da poter semplicemente fare riferimento ai nomi delle costanti enum all'interno del tipo. Questo può aiutare con la leggibilità se usato bene, ma attenzione. TypeProperty
deve essere esposto per essere importato, sebbene possa ancora essere per lo più privato se necessario (può comunque essere contenuto in JavaType
se necessario, non può essere solo private
). Ecco un esempio:
package com.example;
import static com.example.TypeProperty.*;
enum JavaType {
INTEGER(PRIMITIVE, NUMERIC),
BOOLEAN(PRIMITIVE),
STRING(),
/* ... */;
private EnumSet<TypeProperty> properties;
private JavaType(TypeProperty... properties) {
this.properties = EnumSet.copyOf(Arrays.asList(properties));
}
public boolean isPrimitive() {
return properties.contains(PRIMITIVE);
}
public boolean isNumeric() {
return properties.contains(NUMERIC);
}
/* ... */
}
enum TypeProperty {
PRIMITIVE,
NUMERIC,
/* ... */
}
Just to clarify, not all of the properties are booleans.
Se hai alcune proprietà non booleane, puoi metterle all'inizio del costruttore e seguirle con il parametro varargs. È ancora possibile eseguire il problema senza etichetta, ma ti consente di organizzarlo di più. Di 'qualcosa del tipo:
enum JavaType {
INTEGER("int", Integer.class, TypeProperty.PRIMITIVE, TypeProperty.NUMERIC),
BOOLEAN("boolean", Boolean.class, TypeProperty.PRIMITIVE),
STRING("String", String.class),
/* ... */;
private String name;
private Class<?> representationClass;
private EnumSet<TypeProperty> properties;
private JavaType(String name, Class<?> representationClass, TypeProperty... properties) {
this.name = name;
this.representationClass = representationClass;
this.properties = EnumSet.copyOf(Arrays.asList(properties));
}
/* ... code from before ... */
}
Se hai molte proprietà non booleane, allora diventa molto più difficile organizzarle. A quel punto, l'approccio n. 3 potrebbe essere più ragionevole, o in alternativa potresti combinare l'approccio n. 1 e i parametri vararg.