Perché abbiamo bisogno di enumerazioni in lingue tipizzate dinamicamente?


32

Stavo leggendo un po 'di codice qui e ho visto che un enum viene utilizzato per memorizzare i nomi dei tag HTML. Perché mai abbiamo bisogno di farlo? Quali vantaggi ottengo usando questa strategia?

So che sono utili enumerazioni in linguaggi compilati o tipicamente statici, ma quando vedo enumerazioni in linguaggi tipicamente dinamici, mi incuriosisco, come il codice di esempio che ho mostrato sopra. Quindi, la domanda si riduce sostanzialmente al motivo per cui abbiamo bisogno di enumerazioni in un linguaggio tipizzato in modo dinamico o ne abbiamo assolutamente bisogno?


38
Questa domanda è fondamentalmente "Perché abbiamo bisogno dei tipi" .
user11153

1
Hai cercato nel repository per vedere come si chiama? Ciò ti darebbe probabilmente una migliore comprensione delle risposte che hai ricevuto.
RubberDuck,

se hai: enum People { YOU, NPC, FOO, BAR }e una funzione che vuole un (People) int, puoi collegare qualunque cosa, invece di usare un numero.
Evan Carslake,

3
Stai chiedendo lo scopo di questo particolare "enum" o lo scopo degli enum in generale, in qualsiasi lingua? Suppongo che il primo, ma tutte le risposte attuali sembrano pensare al secondo ...
Meriton - in sciopero

Risposte:


56

Un vantaggio è che il compilatore può farti sapere se hai digitato accidentalmente "ADRESS" o "FEILDSET" e ti ha permesso di risolverlo immediatamente invece di comportarti in modo insensato in fase di esecuzione.

Sebbene il vantaggio sia molto più utile nei linguaggi tipicamente statici che dinamici, è comunque utile anche se si tratta di un errore di runtime in quanto riceverai un messaggio che indica un problema con la tua istruzione case piuttosto che con i tuoi dati.


4
@amon: potresti, ma enums ti offre un pratico meccanismo per assicurarti di non avere collisioni.
whatsisname

75
Un posto in cui lavoravo una volta per un mese a inseguire un bug causato dalla brillante idea di qualcuno di usare costanti di stringa invece di enumerazioni, caratteri di editor scadenti e un campo chiamato per caso"PROF1LE_"
Gort the Robot

8
@amon Go fa esattamente questo. Una cosa bella di enum, tuttavia, è che il compilatore può verificare che la vostra istruzione switch abbia un caso per ogni possibile valore enum.
weberc2,

15
Questo codice è stato scritto negli anni '80. Potresti non rendertene conto, ma era in un'epoca in cui alcuni sviluppatori hanno imparato a sviluppare macchine da scrivere fisiche, che potrebbero non avere una chiave . Anche se in realtà mi rendo conto che la stringa in questione era "Profi1e" ... sono passati venticinque anni, quindi la mia memoria non è ovviamente perfetta.
Gort the Robot

4
@DarrelHoffman: sono sorpreso che tu sia sorpreso. In Perl, mi trovo spesso a scrivere $1quando intendo $i. (Certo, non ho mai digitato f1leinvece di file- l' $1errore è innescato dal fatto che $1è molto comune in Perl - ma comunque, errori di ogni genere sono comuni. Forse lo sviluppatore aveva una password con prof1ledentro, in tal modo innescandoli per digitare male profilein contesti senza password.)
ruakh

22

Gli enumeratori sono utili per le situazioni in cui si dispone di un insieme fisso di valori / entità sensibili. Sono auto-documentati e consentono al compilatore di convalidare cose che altrimenti verrebbero lasciate in fase di esecuzione. Non dovrebbero mai essere usati se l'insieme di valori significativi non è noto o non è strettamente limitato.

Un esempio più utile potrebbe essere qualcosa come i codici di risposta HTTP. Invece di avere un metodo che accetta un numero e fornisce il nome e / o la descrizione dell'errore, puoi avere una serie di enumerazioni con nomi significativi, un codice e una descrizione ecc. In un pacchetto pulito che è autorevole in quali valori sono consentito e deve essere gestito.


1
L '"auto-documentazione" è la parte più importante. Preferirei mille volte controllare se status === GEOLOCATION_ACQUIREDche status === 3, in modo che la persona che sostiene che il software capisce cosa sta succedendo. Come hai detto, impedisce anche valori non validi.
Nicolas Bouliane,

11

Gli enum non hanno nulla a che fare con OOP e JavaScript non ha enumerazioni. Invece, gli enum sono usati ogni volta che c'è una scelta tra un set fisso di valori. Ad esempio, un booleano è una scelta tra vero e falso, che potrebbe essere implementato come enum Bool { False, True }. In una libreria GUI, potremmo avere un enum per allineamenti: enum HAlignment { LEFT = -1, CENTER = 0, RIGHT = 1 }.

Di solito è irrilevante come viene implementato l'enum, la parte importante è che ogni possibile valore è distinto. Molte lingue usano numeri interi per gli enum, sebbene alcuni come Java supportino oggetti arbitrari.

Fino ad ora avremmo potuto usare costanti, ad es const int LEFT = -1, CENTER = 0, RIGHT = 1. Tuttavia, un compilatore sa che i valori enum appartengono insieme. Quindi quando cambio i valori enum switch(value) {case LEFT: ...; case RIGHT: ...;}, il compilatore può avvisarmi che ho dimenticato il CENTERcaso. Questo può essere un notevole risparmio di tempo. Nelle lingue senza enumerazioni o senza costrutto di un caso switch, questo può essere simulato con il modello di visitatore, sebbene ciò sia più utile in presenza della tipizzazione statica.

L'altro vantaggio è che gli enum possono essere trattati come un tipo separato. Ad esempio, posso dichiarare che un metodo accetta un HAlignmentparametro, anziché un numero intero. Il codice non verrà quindi compilato se fornisco altro che uno dei tre possibili valori di allineamento. Tuttavia, gli enumeri di C non sono ben incapsulati e le costanti di enum possono essere usate in modo intercambiabile con gli interi. Altre lingue sono più rigorose qui.

In JavaScript, non otteniamo nessuno di questi vantaggi. L'esempio dato dichiara un oggetto che viene trattato come un enum. Ciò presenta alcuni vantaggi per il programmatore, ad esempio semplifica la documentazione, raggruppa tutte le "costanti" in un singolo oggetto, ... Tuttavia, è solo una convenzione che un tale oggetto è simile all'enum.

Il punto qui è che l'HTML ha solo un insieme finito e noto di tag. Puoi guardare le specifiche HTML5 e inserire quei nomi di elementi come enum nel tuo codice, e quindi rendere più difficile intrufolare un <blink>tag nel tuo programma. È meglio codificare questa conoscenza in un posto che sporcare il codice con letterali stringa speciali (o peggio, numeri magici).


In tal caso, se passo <blink>a un metodo in javascript, niente potrebbe fermarmi, giusto? ma javaciao si
scatena

@CodeYogi sì, perché JS non ha un sistema di tipi statici, e in particolare non ha il concetto di tipi di enum. Tuttavia, posso documentare un parametro di metodo come "prende un TagName", il che indurrebbe un programmatore a invocarlo come foo(TagName.STRONG)un po 'meglio. Sarebbe ancora meglio se JS si lamentasse se il campo non esiste, ma qui otterremo un solo undefinedse provo TagName.BLINK. Non vale molto in JS, ma è un inizio.
amon,

Hmm, il link al codice che ho menzionato sopra usa il compilatore di chiusura quindi ha senso lì.
CodeYogi,

Clojure è un linguaggio funzionale, quindi non sono sicuro di come OOP sia rilevante per la domanda, ma a parte questo, è importante distinguere tra enum che sono generalmente solo un insieme di numeri interi (non OO) e il modello 'Typesafe enum' che è OO e ciò che Java supporta.
JimmyJames,

@JimmyJames Sto parlando di JS, non di Clo j ure (che, in esecuzione sulla piattaforma Java, supporta anche OOP in una certa misura). La domanda è stata taggata con oop , motivo per cui la menziono all'inizio. Non vedo davvero come gli enormi typesafe siano collegati a OOP, questa è solo una caratteristica di sistema di tipo (molti linguaggi non-OOP hanno sistemi di tipo :-))
amon

3

Anche se la tua lingua non richiede compilazione, probabilmente utilizzerai una sorta di IDE o strumenti di sviluppo, che possono fornire un supporto molto migliore per qualcosa come un enum che solo per le stringhe.

Se usi un enum come oggetto letterale in javascript, ad esempio, il tuo editor ti darà il completamento del codice e il tuo controllo del codice come JSHint o JSLint ti avviserà, se usi accidentalmente un valore errato.


Penso che molte altre risposte mancino o battano su questo punto. L'uso di una 'emum' in un linguaggio dinamico potrebbe non fare nulla per un compilatore, ma può davvero aiutare alcuni IDE, strumenti di documentazione e non dimenticare gli umani che stanno cercando di capire il codice.
Robert,

2

Il punto di tale enum potrebbe essere quello di fornire a Js Api (goog) un set / bundle di tag consentiti. Quale? Quelli definiti da W3C HTML 4.01 ( consulta la documentazione di enum ). Quindi sono i limiti delle impostazioni.

Potrebbe o non essere questo il vero obiettivo, tuttavia funzionerebbe bene per tale scopo.

Se sai come funziona Javascript, il codice che sta facendo sta definendo un array indicizzato da stringhe :-). Quale valore è una stringa, ma potrebbe essere qualsiasi altro componente con attributi, funzioni, ecc ... Lascia correre la tua immaginazione e vedrai benefici ovunque.

Javascript a parte, uso molto enum per la modellazione e la gestione di macchine a stati .

INIZIO> IN_PROGRESS> CONFERMATO> FINITO> ...

In java switch consente gli enum, quindi è abbastanza facile convalidare gli stati in una macchina a stati , eseguire il ciclo su tutto l'enum, definire le priorità facendo enum complessi, ...

Li uso anche per definire costanti tipizzate e non modificabili:

  • Si No

Anche enumerazioni complesse (che consente di eseguire trasformazioni / parser sicuri)

  • Sì (1, vero), No (0, falso)

A causa degli enum spesso appartiene al mio livello di modello (core), le sue caratteristiche sono accessibili a tutto il sistema, quindi diventa un modello funzionale e mantengo un accoppiamento basso.

Ciò che dà enums (tra le altre cose) sono i confini e la tipizzazione

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.