2011-08-22 14 views
34

quando si definisce un enum per qualcosa che può essere "indefinito" nelle interfacce, si dovrebbeSi dovrebbe definire un valore nullo/sconosciuto per le enumerazioni Java?

  • definire un valore enum separato per questo, o
  • basta usare EnumValue = null per quelle situazioni?

Ad esempio,

serviceX.setPrice (prezzo priceEnum)

enum Price { 
CHEAP, EXPENSIVE, VERRRY_EXPENSIVE, UNKNOWN 
} 

e priceEnum.UNKNOWN quando necessario

o

enum Price { 
CHEAP, EXPENSIVE, VERRRY_EXPENSIVE 
} 

e priceEnum = null quando necessaria?

Avere un piccolo dibattito su questo. Alcuni punti che ti vengono in mente:

  • utilizzando Price.UNKNOWN salva un codice "if (price == null)". Puoi gestire Prezzo x tutti i valori in un singolo switch
  • A seconda della tecnologia di visualizzazione, potrebbe essere più facile localizzare Price.UNKNOWN
  • utilizzando il tipo Price.UNKNOWN di problema "numero magico" nel codice, IMO . Qui abbiamo Price.UNKNOWN, altrove forse Color.UNDEFINED, Height.NULLVALUE, ecc.
  • utilizzando priceValue = null è più uniforme con il modo in cui altri tipi di dati vengono gestiti in Java. Abbiamo Integer i = null, DomainObject x = null, String s = null anche per valori sconosciuti, no?
  • Price.UNKNOWN ti obbliga a decidere se il valore nullo è consentito per tutti i casi d'uso. Potremmo avere metodo prezzo getPrice() che può restituire Price.UNKNOWN e setPrice (Price p) che non è autorizzato ad accettare Price.UNKNOWN. Poiché Price.UNKNOWN è sempre incluso nei valori di enum, quelle interfacce appaiono un po 'sporche. So priceValue = null ha lo stesso problema (non è possibile definire nell'interfaccia se nulla è accettata o no), ma ci si sente un po 'più pulito e un po' meno fuorviante (?)
+7

non è possibile utilizzare "null" in uno switch e questo è uno svantaggio principale. – bestsss

+0

Buoni punti da parte di tutti. Ridurre l'onere della gestione nulla e la capacità di essere più specifici su cosa significhi "valore nullo" punti buoni per Price.UNKNOWN. Inoltre, buon punto su "modello oggetto nullo", rende Price.UNKNOWN più una soluzione "valida" e comunemente accettata. Ma nessuno si sente allo stesso modo su Price.UNKNOWN aspetti negativi? Ritengo che avere Price.UNKNOWN inquini il set di valori dell'enum. Dì in showAllPrices(), non posso più enumerare tutti i valori enum, devo aggiungere se (! Price.UNKNOWN), che sembra un po 'sporco e "magico-numeroso". – user449236

+0

* @ user449236 *: Se non ti piace controllare questo valore speciale, aggiungi un flag 'display' a ogni enumerazione e controllalo. Più pulito e più flessibile. –

risposta

12

direi andare con Price.UNKNOWN se questo è un valore valido per un prezzo.

Sono d'accordo con gli inconvenienti di trattare riferimenti null che menzioni, e penso che motivino abbastanza la decisione.

Nuovi linguaggi, per esempio Scala (e alcuni più vecchi, Haskell) si allontanano dai riferimenti nulli tutti insieme e utilizza l'opzione/forse le monade invece ... per buoni motivi.

27

Questo è in realtà un esempio di applicazione di Null Object pattern. IMHO è sempre meglio avere un oggetto fittizio anziché null. Ad esempio, è possibile aggiungere metodi fittizi a oggetti nulli anziché distribuire il codice con controlli null ovunque. Molto conveniente.

anche il nome del enum ti dà alcune semantiche aggiuntive: è il prezzo sconosciuta, indefinita, non affidabile, non ancora noti ? E cosa significa se il prezzo è nullo?

AGGIORNAMENTO: come Aaron Digulla indica, il modello Oggetto nullo richiede memoria. Ma in realtà non è il caso per la maggior parte del tempo. Nell'implementazione tradizionale di solito si ha un singleton per l'oggetto Null utilizzato ovunque poiché non è necessario istanze separate. Diventa ancora meglio con le enumerazioni perché ottieni la semantica singleton gratuitamente.

Un altro punto è che il riferimento null e il riferimento a qualche oggetto occupano la stessa quantità di memoria (ad esempio 4 byte sulla macchina a 32 bit). È l'oggetto a cui viene fatto riferimento che occupa parte della memoria aggiuntiva. Ma se questo è un singleton, qui non c'è praticamente memoria in testa.

+0

+1 per aver menzionato il modello. Un punto da notare: il motivo principale per cui le persone non usano il modello è perché ha bisogno di memoria (i puntatori nulli non hanno bisogno di memoria). Ma dimenticano che questo rende il codice più complesso (-> più tempo speso per svilupparlo e debuggarlo), la complessità è fortemente correlata al numero di bug e più code line significa che il * codice * ha bisogno di più memoria, quindi quella decisione è spesso un perdita su * tutte * le frontiere. –

+0

Buon punto, ho effettivamente modificato la mia domanda per indirizzare il tuo commento. –

+0

'Il motivo principale per cui le persone non usano il pattern è perché ha bisogno di memoria (i puntatori nulli non hanno bisogno di memoria)' il motivo principale è il rendimento dato che i controlli nulli sono facilmente eliminati dal JIT, i controlli null sono assistiti da hardware e così via . – bestsss

1

Dipende da come userai questa enumerazione. Se lo usi nelle istruzioni switch/case, non importa. Se si creano metodi nell'enumerazione, è necessario definire SCONOSCIUTO.

Per esempio è possibile definire metodo astratto public abstract Icon icon();

nella vostra enum e quindi implementare questo metodo per ogni membro del Prezzo. Probabilmente vorrai visualizzare il punto interrogativo a un prezzo sconosciuto. In questo caso basta implementare il metodo icon() che crea un'icona appropriata.

1

C'è lo Enum-Switch-Null-Trap. Quindi sembra che, proprio come con qualsiasi proprietà che sia un oggetto, se non esiste, allora è null.

0

Colore o Altezza verrebbero utilizzati nella logica del programma. Non possono gestire con un colore non definito. A Il prezzo è dato utente e potrebbe essere sconosciuto. Il colore può essere un altro utente, ma per essere usato come colore nel codice, è necessario definirli.

Quindi il prezzo può essere SCONOSO (anziché null), Colore non (null può indicare errore).

Problemi correlati