Ovviamente ci sono piu modi di realizzare la cosa.
Se lo scopo è entrare nella filosofia della programmazione ad oggetti, inizierei a scommporre il problema in sottoproblemi e a pensare alle classi con cui implementare i vari moduli. Ad esempio, io userei una classe che rappresenta un'operazione; tale classe contiene gli operandi ed è in grado di eseguire l'operazione tra gli operandi.
Un'altra classe invece puo occupasrsi di fare il parsing dell'input dell'utente per ricavarne un oggetto che rappresenta un'operazione.
La Calcolatrice userebbe il Parser per interpretare l'input dell'utente, ovvero ricavare dall'input un oggetto oprazione, dopodichè può invocare un opportuno metodo sull'oggetto operazione per eseguire effettivamente l'operazione che rappresenta.
Questo approccio è molto aderente alla filosofia della progrmmazione ad oggetti, la calcolatrice non ha bisogno di preoccuparsi di come implementare le operazioni: saranno le apposite classi a fare questo; analogamente la calcolatrice non deve preoccuparsi di come effettuare il parsing: se domani decidi che i dati devono essere immessi in modo diverso è sufficiente implementare diversamenete solo la classe Parser; se vuoi aggiungere altre operazioni devi solo definire le relative classi.
Qui di seguito ti riporto in forma stringata le classi che io userei:
Codice PHP:
//E l'interfaccia che deve essere implemetate dalle classi che rappresentano un'operazione
interface Operazione{
public double calcola();
}
//E una classe che rappresenta un'operazione unaria
//è astratta perche il metodo calcola non è implementato
abstract classe OperazioneUnaria implements Operazione{
protected double primoOperando;
public OperazioneUnaria(double operando){
primoOperando = operando;
}
public abstract double calacla();
}
//Questa classe rappresenta un'operazione binaria aggiungendo
//un secondo operando; anche questa è astratta
abstract classe OperazioneBinaria extends OperazioneUnaria{
protected double secondoOperando;
public OperazioneUnaria(double operando1, double operando2){
super(operando1);
secondoOperandoOperando = operando;
}
public abstract double calacla();
}
//Poi fai le varie implementazioni, in base alle diverse operazioni;
class RadiceQuadrata extends OperazioneUnaria{
public double calcola(){
return Math.sqrt(primoOperando);
}
}
class Moltiplicazione extends OperazioneBinaria{
public double calcola(){
return primoOperando * secondoOperando;
}
}
e cosi per le altre operazioni che vuoi implementare
Subito dopo potresti pensare ad una classe Parser che riceve una stringa e capisce che operazione bisonga fare. Tale classe può offrire ad esempio un metodo pubblico parse(String s) che restituisce un oggetto di una classe che implementa Operazione.
Codice PHP:
class Parser{
public static Operazione parse(String s){
//Supponiamo che la stringa s sia 4 * 2
//Allora bisogna fare una moltiplicazione:
return new Moltiplicazione(4, 2);
//Supponiamo che la stringa s sia 4 / 2
//Allora bisogna fare una divisione:
return new Divisione(4, 2);
//eccetera eccetera...
}
}
Ora, avendo queste classi a disposizione, una Calcolatrice deve semplicemente eseguire un ciclo continuo in cui:
1 - prende una stringa s di input dall'utente;
2 - invoca il metodo Parser.parse(s) della classe Parser, ottenendo un oggetto op che è un'Operazione;
3 - invocare su op il metodo calcola per avere i risultato e stamparlo.
Codice PHP:
class Calcolatrice{
private void execute(){
String s = null;
while(true){
System.out.println("Immetti l'operazione da eseguire");
String s = //....s contiene l'iput dell'utente
Operazione op = Parser.parse(s);
float rislutato = op.calcola();
System.out.println("il risultato è " + risultato);
}
}
}
Nota: la calcolatrice non sa neanche se l'operazione che esegue è unaria o binaria, ma poichè ogni classe che rappresenta un'operazione implementa l'iterfaccia Operazione, la Calcolatrice sa che basta invocare il metodo calcola() per averne il risulatato.