Come progettare l'ereditarietà dalla classe astratta che non è iniziata ma apparentemente deve essere iniziata?

0

Ho bisogno di progettare un programma in Java che calcola le espressioni aritmetiche (solo addizioni o sottrazioni).

Requirements:

1) abstract class Expression which contains abstract method calculate() and method equals() which overrides Object.

2) concrete class AtomicExpression which inherits from Expression and must have a constructor which receives a real number. This class represents a single number.

3) abstract class CompoundExpression which inherits from Expression and has a constructor which receives 2 Expression objects (two operands). This class represents an arithmetic expression with 2 operands.

4) concrete classesAdditionExpression and SubtractionExpression whose constructors also receive 2 Expression objects. These classes actually calculate the expressions with 2 operands.

Il mio istinto naturale era quello di aggiungere un campo di istanza result e un costruttore a Expression che avrebbe archiviato il risultato di un'espressione. Se si tratta di un'espressione atomica, il risultato sarebbe il numero stesso. Se abbiamo a che fare con un'espressione composta, memorizzeremo il risultato dell'espressione in result . Ma poi CompoundExpression eredita anche da Expression e riceve 2% oggettiExpression nel proprio costruttore. Quindi CompoundExpression non può realmente inizializzare il suo genitore ( Expression ha un campo, CompoundExpression riceve due parametri).

Se dovessi rinunciare a un costruttore in Expression , non posso davvero sovrascrivere equals in Expression perché devo essere in grado di fare un confronto basato su un campo.

Come posso risolvere questo enigma?

    
posta Yos 14.11.2017 - 15:46
fonte

1 risposta

3

Stai lavorando con ciò che potremmo chiamare un Abstract Syntax Tree .

Lo scopo dell'albero è catturare un'espressione. Esistono altri modi per catturare espressioni, come il testo. Un modulo di testo è una serializzazione . In alcune serializzazioni di espressioni (ad es. infix ), dobbiamo usare la parentesi - () per sovrascrivere la precedenza degli operatori ; tuttavia, in un AST, la precedenza dell'operatore è esplicita nella forma dell'albero, quindi nessuna parentesi è necessaria.

Catturiamo le espressioni come alberi per una serie di motivi. Nella tecnologia del compilatore, le espressioni sono spesso rappresentate come alberi in qualche punto del processo di traduzione (ad esempio parse output). Il compito del compilatore è di tradurre l'espressione in un modulo (di solito di livello inferiore, come codice byte o codice macchina) per l'esecuzione successiva (o ulteriore traduzione per l'esecuzione successiva).

Tale albero potrebbe anche essere valutato invece di tradotto; questo potrebbe accadere, per esempio, in un interprete. In un interprete, in genere, la valutazione di un albero di espressione del genere si verifica dopo la costruzione dell'albero; questo perché l'interprete può scegliere di analizzare l'espressione (albero) prima della valutazione, e / o, perché l'interprete vuole essere in grado di valutare l'espressione più di una volta - ogni volta con valori potenzialmente diversi per le variabili, quindi la stessa espressione può produrre un risultato finale diverso se le variabili vengono aggiornate.

Nel tuo caso in quanto non ci sono variabili (solo costanti), non c'è (ovvio) vantaggio nel ritardare l'esecuzione - quindi potrebbe essere tentato di prendere in considerazione l'esecuzione come parte della costruzione. Ciò implicherebbe avere un risultato o un valore per tutte le entità prima della costruzione, e quindi potresti fornire, nella classe base astratta, un costruttore che riceve il valore e un campo che contiene il valore; tuttavia, come si nota, ciò richiede che anche CompoundExpression e AdditionExpression vengano costruiti in termini di valori, e questo sarebbe un compito diverso.

Secondo il testo dei tuoi requisiti, (1) devi fornire un metodo calculate() per la valutazione (post-costruzione) dell'espressione, e (2) devi fornire un costruttore per AdditionExpression che prende il due% diExpression se nessun valore !!

Il tuo compito è supportare la costruzione di alberi per una valutazione successiva, non per costruire un albero e contemporaneamente calcolare il suo valore finale. Quindi, separa questi concetti nella tua mente: la costruzione dell'albero dalla valutazione dell'albero. La valutazione verrà effettuata dopo la costruzione.

If I were to forgo a constructor in Expression then I can't really override equals in Expression because I need to be able to make comparison based on some field.

Per ripetermi, stai confondendo la costruzione con la valutazione. Nel modello di tali requisiti, la costruzione avviene prima e la valutazione viene posticipata fino al completamento della costruzione.

L'override di equals(...) verrà eseguito solo nell'ambiente post-costruzione. Nessuno chiamerà equals durante la costruzione dell'albero, eh?

Quindi, nel tuo equals override puoi presumere che gli alberi siano completamente costruiti! Alberi completamente costruiti supportano l'interfaccia fornita dalla classe astratta Expression - possono essere valutati per ottenere il loro valore!

    
risposta data 14.11.2017 - 18:45
fonte

Leggi altre domande sui tag