Perché utilizzare un enum per determinare il tipo di nodo in un albero di analisi?

4

L'API Sun Compiler Tree utilizza un'interfaccia chiamata Albero come genitore di tutti i diversi tipi di nodi dell'albero di analisi (assegnazioni, istruzioni if, dichiarazioni di classe, ecc.). Una parte di questa interfaccia è un'enumerazione chiamata Tipo che contiene il tipo di nodo.

Devo ancora incontrare un caso in cui l'enum non è fedele al tipo di nodo come un oggetto Java. Qual è il vantaggio ottenuto qui? Solo per aprire la porta per cambiare le dichiarazioni? Che cosa significa raggiungere questo polimorfismo?

    
posta Alex Reinking 10.03.2015 - 16:49
fonte

4 risposte

5

Un enum modella un insieme di finite di diverse scelte in cui devi sapere con chi hai a che fare prima di poter procedere. La spedizione dinamica risolve un problema completamente diverso, consentendo un numero illimitato di opzioni e gestendole in modo uniforme.

Un enum è probabilmente più efficiente e generalmente più sicuro dell'ispezione della classe del nodo:

if (node instanceof Type1Node) {
    ...
} else if (node instanceof Type2Node) {
    ...
} else {
    throw new AssertionError("Someone added a new node type.");
}

VS

switch (node.type) {
case Tree.Kind.AND:
    ...
case Tree.Kind.AND_ASSIGNMENT:
    ...
}
throw new AssertionError("Someone modified this enum");

La versione enum ha un solo salto e riceverai avvertimenti se ti perdi qualche caso, per negligenza o perché l'enum è stato aggiornato. Non puoi ottenere questi avvisi con una tonnellata di test instanceof perché è possibile aggiungere nuove sottoclassi.

Un'alternativa ragionevole è usare una qualche forma di Visitor . Ma anche con lambda che consente una sintassi più compatta per i visitatori, ci sono ancora dei vantaggi in switch : puoi facilmente unire più casi ogni volta che vengono gestiti allo stesso modo.

    
risposta data 10.03.2015 - 17:20
fonte
3

Quale sarebbe un'alternativa a enum s?

Un tipo integrale non formalizzato? Questo è un passo indietro. Fare tutte le distinzioni per invio dinamico su metodi di sottoclasse del tipo di nodo? Questo funziona solo per alcuni problemi; nelle lingue senza invio multiplo, ci sono molte situazioni che non puoi gestire in questo modo. Se la lingua non offre un'opzione migliore, switch ing su enum è esattamente la cosa giusta da fare.

    
risposta data 10.03.2015 - 16:59
fonte
2

In particolare per gli alberi da analizzare, è molto raro usare il polimorfismo. Richiederebbe al tipo di nodo base di conoscere tutte le diverse capacità / proprietà / attributi di ogni diverso tipo di nodo nella struttura di analisi. Questo può sfuggire di mano rapidamente.

Usando un enum, è più facile costruire visitatori che camminino sull'albero e ci facciano le cose a seconda del nodo che stanno visitando. Poiché questo tipo di visita è il modello di utilizzo comune per l'analisi statica, l'ottimizzazione e la compilazione del back-end, è logico renderlo più semplice.

    
risposta data 10.03.2015 - 17:00
fonte
1

In primo luogo, credo che tu lo sappia, ma potrebbe non essere chiaro agli altri lettori. L'interfaccia in questione fornisce entrambi un enum e un dispiegamento polimorfico tramite lo schema del visitatore. Detto questo, penso che in generale dovresti preferire usare il polimorfismo, se puoi farlo in modo pulito senza duplicazione.

Penso che le enumerazioni non siano necessariamente necessarie per le dichiarazioni di switch, ma per altre strutture semplificatrici. Puoi usarli per indicizzare un map , ad esempio. Potresti creare una matrice KindsWithConditionals . È possibile memorizzare un enum tipo in una colonna del database. Puoi facilmente registrarlo con toString . Ci sono molte cose che puoi fare con un enume ingombrante senza uno.

    
risposta data 10.03.2015 - 17:55
fonte

Leggi altre domande sui tag