Calcolatrice con eventi java

Fab996

Utente Attivo
177
5
Volevo chiedere qualche consiglio su come poter migliorare il codice
Questo è il codice relativo al main
Codice:
import javax.swing.*;import java.awt.*;
import java.awt.event.*;
//la mia calcolatrice è un jframe(per polimorfismo) quindi siccome estendo la classe posso applicare tutti i metodi di jframe!!!
class Calcolatrice extends JFrame {
    public JButton zero,uno,due,tre,quattro,cinque,sei,sette,otto,nove,div,molt,som,sotr,virgola,segno,uguale,radice,percent,definire,cancellaC,cancellaCE;
    public JLabel etichetta;
    public String cont = "";
    public double accumulatore = 0;
    public double salvauno=0;
    public double totale;
    public Object o;
    //inserire una variabile temporanea che contiene il valore attuale prima dell'eventuale operazione
    //public seconda,prima;
    //costruttore
    public Calcolatrice() {
        super("Calcolatrice"); //invoca costruttore di JFrame
        ActionListener asc = new Event(this);
        this.setSize(320,300);// il this si riferisce all'oggetto corrente ossia la calcolatrice
        this.setMinimumSize(new Dimension(320,300));
        this.setMaximumSize(new Dimension(500,500));
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(true);
        this.inizializzaGUI();    
        this.zero.addActionListener(asc);
        this.uno.addActionListener(asc);
        this.due.addActionListener(asc);
        this.tre.addActionListener(asc);
        this.quattro.addActionListener(asc);
        this.cinque.addActionListener(asc);
        this.sei.addActionListener(asc);
        this.sette.addActionListener(asc);
        this.otto.addActionListener(asc);
        this.nove.addActionListener(asc);
        this.som.addActionListener(asc);
        this.uguale.addActionListener(asc);
        this.molt.addActionListener(asc);
        this.div.addActionListener(asc);
        this.sotr.addActionListener(asc);
        this.cancellaC.addActionListener(asc);
        this.radice.addActionListener(asc);
        this.setVisible(true);
    } 
    public void inizializzaGUI() {
        Container c = this.getContentPane(); //il this è un riferimento all'oggetto di tipo JFrame
        c.setLayout(new GridLayout(6,1));
        JPanel tasti3; //pannello secondario per i tasti
        JPanel tasti4;
        JPanel tasti5;
        JPanel tasti6;
        JPanel cancella; //pannello secondario per cancellare
        // costruzione dei tre pannelli col rispettivo layout
        tasti3 = new JPanel(new GridLayout(1,5));
        tasti4 = new JPanel(new GridLayout(1,5));
        tasti5 = new JPanel(new GridLayout(1,5));
        tasti6 = new JPanel(new GridLayout(1,5));
        cancella = new JPanel(new GridLayout(1,2));
        //assegnazione componenti 
        etichetta = new JLabel("0");
        cancellaC = new JButton("C");
        cancellaCE = new JButton("CE");
        zero = new JButton("0");
        uno = new JButton("1");
        due = new JButton("2");    
        tre = new JButton("3");
        quattro = new JButton("4");
        cinque = new JButton("5");
        sei = new JButton("6");
        sette = new JButton("7");
        otto = new JButton("8");
        nove = new JButton("9");
        div = new JButton("/");
        molt = new JButton("*");
        som = new JButton("+");
        sotr = new JButton("-");
        virgola = new JButton(".");
        segno = new JButton("+/-");
        uguale = new JButton("=");
        radice = new JButton("sqrt");
        percent = new JButton("%");
        definire = new JButton("1/x");
        //aggiunta dei vari componenti
        cancella.add(cancellaCE);
        cancella.add(cancellaC);
        tasti3.add(sette);
        tasti3.add(otto);
        tasti3.add(nove);
        tasti3.add(div);
        tasti3.add(radice);
        tasti4.add(quattro);
        tasti4.add(cinque);
        tasti4.add(sei);
        tasti4.add(molt);
        tasti4.add(percent);
        tasti5.add(uno);
        tasti5.add(due);
        tasti5.add(tre);
        tasti5.add(sotr);
        tasti5.add(definire);
        tasti6.add(zero);
        tasti6.add(segno);
        tasti6.add(virgola);
        tasti6.add(som);
        tasti6.add(uguale);
        //aggiunta dei vari pannelli al ContentPane
        c.add(etichetta);
        c.add(cancella);
        c.add(tasti3);    
        c.add(tasti4);
        c.add(tasti5);
        c.add(tasti6);
    }
    public void mostrazero() {
        etichetta.setText(this.cont+"0");
        this.cont = this.cont+"0";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostrauno() {
        etichetta.setText(this.cont+"1");
        this.cont = this.cont+"1";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostradue() {
        etichetta.setText(this.cont+"2");
        this.cont = this.cont+"2";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostratre() {
        etichetta.setText(this.cont+"3");
        this.cont = this.cont+"3";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostraquattro() {
        etichetta.setText(this.cont+"4");
        this.cont = this.cont+"4";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostracinque() {
        etichetta.setText(this.cont+"5");
        this.cont = this.cont+"5";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostrasei() {
        etichetta.setText(this.cont+"6");
        this.cont = this.cont+"6";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostrasette() {
        etichetta.setText(this.cont+"7");
        this.cont = this.cont+"7";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostraotto() {
        etichetta.setText(this.cont+"8");
        this.cont = this.cont+"8";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostranove() {
        etichetta.setText(this.cont+"9");
        this.cont = this.cont+"9";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void operazioni(Object t) {  //vale per qualsiasi operazione;
        etichetta.setText("0");
        this.cont = "";
        salvauno = totale+this.accumulatore;
        System.out.println(this.accumulatore);
        System.out.println(this.salvauno); 
        this.accumulatore = 0;
        o = t;
    }
    public void calcola() {
        if(o==this.som) {
            totale = salvauno+this.accumulatore;
            etichetta.setText(String.valueOf(totale));
        }
        else if (o==this.molt) {
            totale = salvauno*this.accumulatore;
            etichetta.setText(String.valueOf(totale));
        }
        else if (o==this.div) {
            totale = salvauno/this.accumulatore;
            etichetta.setText(String.valueOf(totale));
        }
        else if (o==this.sotr) {
            totale = salvauno-this.accumulatore;
            etichetta.setText(String.valueOf(totale));
        }
        else if (o==this.radice) {
            totale = Math.sqrt(this.accumulatore);
            etichetta.setText(String.valueOf(totale));
        }
        this.accumulatore=0;
    }
    public void azzera() {
        etichetta.setText("0");
        this.cont="";
        this.accumulatore = 0;
        this.salvauno = 0;
        this.totale = 0;
    }
    public static void main(String[] args) {
        Calcolatrice c = new Calcolatrice(); //per polimorfismo posso anche fare JFrame c =...
    }
}
Mentre questo è il codice relativo alla gestione degli eventi
Codice:
import java.awt.event.*;class Event implements ActionListener {
    //l'ascoltatore deve accedere all'applicazione
    private Calcolatrice pib;
    //inizializzo l'oggetto Listener
    public Event(Calcolatrice c) {
        this.pib = c;
    }
    //capisce quale evento accade e se accate tale evento fa partire il metodo
    public void actionPerformed(ActionEvent e) {
        if    (e.getSource()==this.pib.zero)
            this.pib.mostrazero();
        else if (e.getSource()==this.pib.uno)    
            this.pib.mostrauno();
        else if (e.getSource()==this.pib.due)
            this.pib.mostradue();
        else if (e.getSource()==this.pib.tre)
            this.pib.mostratre();
        else if (e.getSource()==this.pib.quattro)
            this.pib.mostraquattro();
        else if (e.getSource()==this.pib.cinque)
            this.pib.mostracinque();
        else if (e.getSource()==this.pib.sei)
            this.pib.mostrasei();
        else if (e.getSource()==this.pib.sette)
            this.pib.mostrasette();
        else if (e.getSource()==this.pib.otto)
            this.pib.mostraotto();
        else if (e.getSource()==this.pib.nove)
            this.pib.mostranove();
        else if (e.getSource()==this.pib.som || e.getSource()==this.pib.molt || e.getSource()==this.pib.div || e.getSource()==this.pib.sotr || e.getSource()==this.pib.radice)
            this.pib.operazioni(e.getSource());
        else if (e.getSource()==this.pib.uguale)
             this.pib.calcola();
        else if (e.getSource()==this.pib.cancellaC)
            this.pib.azzera();
    }
}
Più che altro la calcolatrice funziona solo non capisco perchè se eseguo in sequenza operazioni di moltiplicazione e divisione(sfruttando la proprietà associativa) non funziona bene tipo 6*4*2=48 per le moltiplicazioni e divisioni devo fare le operazioni due a due(per esempio 6*4 poi premere uguale = 24 e poi moltiplicare 24 per 2, e quindi non posso fare direttamente 6*4*2=48, mentre con addizione e sottrazione si), poi non capisco perchè se eseguo 3+2*5=13 non funziona bene...
Inoltre nel main posso fare Calcolatrice c = new Calcolatrice(); ma anche JFrame c = new Calcolatrice(); per il polimorfismo?
Inoltre non capisco perchè nel costruttore Calcolatrice(), posso fare ActionListener asc = new Event(this); come parametro gli passo l'oggetto corrente, ossia la calcolatrice per inizializzare il listener in quanto deve poter accedere alla mia applicazione, ma non capisco perchè Event sia di tipo ActionListener...
Grazie per gli eventuali consigli :)
 

Skills07

Head of Development
Staff Forum
Utente Èlite
35,429
11,501
CPU
Ryzen 7 5800x
Dissipatore
Deepcool gammax l240 v2
Scheda Madre
Aourus Gigabyte X-470 ultra gaming
HDD
Samsung Evo 850 250gb ,2tb x 2 toshiba P300, 256 Ssd silicon power, Samsung evo plus 1tb nvme
RAM
32 gb G.Skill Tridentz 3200 mhz RGB
GPU
Zotac - RTX 3070 Ti Trinity OC
Monitor
ASUS TUF QHD 165hz IPS, ITEK GCF 165hz IPS QHD, Samsung Curvo 144hz QHD
PSU
Seasonic Focus 650w 80 platinum
Case
Coolermaster h500p
Periferiche
Asus Tuf Wireless
Net
Fibra Tim 100mb
OS
Windows 10 Pro 64 bit
Volevo chiedere qualche consiglio su come poter migliorare il codice
Questo è il codice relativo al main
Codice:
import javax.swing.*;import java.awt.*;
import java.awt.event.*;
//la mia calcolatrice è un jframe(per polimorfismo) quindi siccome estendo la classe posso applicare tutti i metodi di jframe!!!
class Calcolatrice extends JFrame {
    public JButton zero,uno,due,tre,quattro,cinque,sei,sette,otto,nove,div,molt,som,sotr,virgola,segno,uguale,radice,percent,definire,cancellaC,cancellaCE;
    public JLabel etichetta;
    public String cont = "";
    public double accumulatore = 0;
    public double salvauno=0;
    public double totale;
    public Object o;
    //inserire una variabile temporanea che contiene il valore attuale prima dell'eventuale operazione
    //public seconda,prima;
    //costruttore
    public Calcolatrice() {
        super("Calcolatrice"); //invoca costruttore di JFrame
        ActionListener asc = new Event(this);
        this.setSize(320,300);// il this si riferisce all'oggetto corrente ossia la calcolatrice
        this.setMinimumSize(new Dimension(320,300));
        this.setMaximumSize(new Dimension(500,500));
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setResizable(true);
        this.inizializzaGUI();    
        this.zero.addActionListener(asc);
        this.uno.addActionListener(asc);
        this.due.addActionListener(asc);
        this.tre.addActionListener(asc);
        this.quattro.addActionListener(asc);
        this.cinque.addActionListener(asc);
        this.sei.addActionListener(asc);
        this.sette.addActionListener(asc);
        this.otto.addActionListener(asc);
        this.nove.addActionListener(asc);
        this.som.addActionListener(asc);
        this.uguale.addActionListener(asc);
        this.molt.addActionListener(asc);
        this.div.addActionListener(asc);
        this.sotr.addActionListener(asc);
        this.cancellaC.addActionListener(asc);
        this.radice.addActionListener(asc);
        this.setVisible(true);
    } 
    public void inizializzaGUI() {
        Container c = this.getContentPane(); //il this è un riferimento all'oggetto di tipo JFrame
        c.setLayout(new GridLayout(6,1));
        JPanel tasti3; //pannello secondario per i tasti
        JPanel tasti4;
        JPanel tasti5;
        JPanel tasti6;
        JPanel cancella; //pannello secondario per cancellare
        // costruzione dei tre pannelli col rispettivo layout
        tasti3 = new JPanel(new GridLayout(1,5));
        tasti4 = new JPanel(new GridLayout(1,5));
        tasti5 = new JPanel(new GridLayout(1,5));
        tasti6 = new JPanel(new GridLayout(1,5));
        cancella = new JPanel(new GridLayout(1,2));
        //assegnazione componenti 
        etichetta = new JLabel("0");
        cancellaC = new JButton("C");
        cancellaCE = new JButton("CE");
        zero = new JButton("0");
        uno = new JButton("1");
        due = new JButton("2");    
        tre = new JButton("3");
        quattro = new JButton("4");
        cinque = new JButton("5");
        sei = new JButton("6");
        sette = new JButton("7");
        otto = new JButton("8");
        nove = new JButton("9");
        div = new JButton("/");
        molt = new JButton("*");
        som = new JButton("+");
        sotr = new JButton("-");
        virgola = new JButton(".");
        segno = new JButton("+/-");
        uguale = new JButton("=");
        radice = new JButton("sqrt");
        percent = new JButton("%");
        definire = new JButton("1/x");
        //aggiunta dei vari componenti
        cancella.add(cancellaCE);
        cancella.add(cancellaC);
        tasti3.add(sette);
        tasti3.add(otto);
        tasti3.add(nove);
        tasti3.add(div);
        tasti3.add(radice);
        tasti4.add(quattro);
        tasti4.add(cinque);
        tasti4.add(sei);
        tasti4.add(molt);
        tasti4.add(percent);
        tasti5.add(uno);
        tasti5.add(due);
        tasti5.add(tre);
        tasti5.add(sotr);
        tasti5.add(definire);
        tasti6.add(zero);
        tasti6.add(segno);
        tasti6.add(virgola);
        tasti6.add(som);
        tasti6.add(uguale);
        //aggiunta dei vari pannelli al ContentPane
        c.add(etichetta);
        c.add(cancella);
        c.add(tasti3);    
        c.add(tasti4);
        c.add(tasti5);
        c.add(tasti6);
    }
    public void mostrazero() {
        etichetta.setText(this.cont+"0");
        this.cont = this.cont+"0";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostrauno() {
        etichetta.setText(this.cont+"1");
        this.cont = this.cont+"1";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostradue() {
        etichetta.setText(this.cont+"2");
        this.cont = this.cont+"2";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostratre() {
        etichetta.setText(this.cont+"3");
        this.cont = this.cont+"3";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostraquattro() {
        etichetta.setText(this.cont+"4");
        this.cont = this.cont+"4";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostracinque() {
        etichetta.setText(this.cont+"5");
        this.cont = this.cont+"5";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostrasei() {
        etichetta.setText(this.cont+"6");
        this.cont = this.cont+"6";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostrasette() {
        etichetta.setText(this.cont+"7");
        this.cont = this.cont+"7";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostraotto() {
        etichetta.setText(this.cont+"8");
        this.cont = this.cont+"8";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void mostranove() {
        etichetta.setText(this.cont+"9");
        this.cont = this.cont+"9";
        this.accumulatore = Integer.parseInt(this.cont);
    }
    public void operazioni(Object t) {  //vale per qualsiasi operazione;
        etichetta.setText("0");
        this.cont = "";
        salvauno = totale+this.accumulatore;
        System.out.println(this.accumulatore);
        System.out.println(this.salvauno); 
        this.accumulatore = 0;
        o = t;
    }
    public void calcola() {
        if(o==this.som) {
            totale = salvauno+this.accumulatore;
            etichetta.setText(String.valueOf(totale));
        }
        else if (o==this.molt) {
            totale = salvauno*this.accumulatore;
            etichetta.setText(String.valueOf(totale));
        }
        else if (o==this.div) {
            totale = salvauno/this.accumulatore;
            etichetta.setText(String.valueOf(totale));
        }
        else if (o==this.sotr) {
            totale = salvauno-this.accumulatore;
            etichetta.setText(String.valueOf(totale));
        }
        else if (o==this.radice) {
            totale = Math.sqrt(this.accumulatore);
            etichetta.setText(String.valueOf(totale));
        }
        this.accumulatore=0;
    }
    public void azzera() {
        etichetta.setText("0");
        this.cont="";
        this.accumulatore = 0;
        this.salvauno = 0;
        this.totale = 0;
    }
    public static void main(String[] args) {
        Calcolatrice c = new Calcolatrice(); //per polimorfismo posso anche fare JFrame c =...
    }
}
Mentre questo è il codice relativo alla gestione degli eventi
Codice:
import java.awt.event.*;class Event implements ActionListener {
    //l'ascoltatore deve accedere all'applicazione
    private Calcolatrice pib;
    //inizializzo l'oggetto Listener
    public Event(Calcolatrice c) {
        this.pib = c;
    }
    //capisce quale evento accade e se accate tale evento fa partire il metodo
    public void actionPerformed(ActionEvent e) {
        if    (e.getSource()==this.pib.zero)
            this.pib.mostrazero();
        else if (e.getSource()==this.pib.uno)    
            this.pib.mostrauno();
        else if (e.getSource()==this.pib.due)
            this.pib.mostradue();
        else if (e.getSource()==this.pib.tre)
            this.pib.mostratre();
        else if (e.getSource()==this.pib.quattro)
            this.pib.mostraquattro();
        else if (e.getSource()==this.pib.cinque)
            this.pib.mostracinque();
        else if (e.getSource()==this.pib.sei)
            this.pib.mostrasei();
        else if (e.getSource()==this.pib.sette)
            this.pib.mostrasette();
        else if (e.getSource()==this.pib.otto)
            this.pib.mostraotto();
        else if (e.getSource()==this.pib.nove)
            this.pib.mostranove();
        else if (e.getSource()==this.pib.som || e.getSource()==this.pib.molt || e.getSource()==this.pib.div || e.getSource()==this.pib.sotr || e.getSource()==this.pib.radice)
            this.pib.operazioni(e.getSource());
        else if (e.getSource()==this.pib.uguale)
             this.pib.calcola();
        else if (e.getSource()==this.pib.cancellaC)
            this.pib.azzera();
    }
}
Più che altro la calcolatrice funziona solo non capisco perchè se eseguo in sequenza operazioni di moltiplicazione e divisione(sfruttando la proprietà associativa) non funziona bene tipo 6*4*2=48 per le moltiplicazioni e divisioni devo fare le operazioni due a due(per esempio 6*4 poi premere uguale = 24 e poi moltiplicare 24 per 2, e quindi non posso fare direttamente 6*4*2=48, mentre con addizione e sottrazione si), poi non capisco perchè se eseguo 3+2*5=13 non funziona bene...
Inoltre nel main posso fare Calcolatrice c = new Calcolatrice(); ma anche JFrame c = new Calcolatrice(); per il polimorfismo?
Inoltre non capisco perchè nel costruttore Calcolatrice(), posso fare ActionListener asc = new Event(this); come parametro gli passo l'oggetto corrente, ossia la calcolatrice per inizializzare il listener in quanto deve poter accedere alla mia applicazione, ma non capisco perchè Event sia di tipo ActionListener...
Grazie per gli eventuali consigli :)


gli eventi potresti gestirli con uno switch case.
 

Skills07

Head of Development
Staff Forum
Utente Èlite
35,429
11,501
CPU
Ryzen 7 5800x
Dissipatore
Deepcool gammax l240 v2
Scheda Madre
Aourus Gigabyte X-470 ultra gaming
HDD
Samsung Evo 850 250gb ,2tb x 2 toshiba P300, 256 Ssd silicon power, Samsung evo plus 1tb nvme
RAM
32 gb G.Skill Tridentz 3200 mhz RGB
GPU
Zotac - RTX 3070 Ti Trinity OC
Monitor
ASUS TUF QHD 165hz IPS, ITEK GCF 165hz IPS QHD, Samsung Curvo 144hz QHD
PSU
Seasonic Focus 650w 80 platinum
Case
Coolermaster h500p
Periferiche
Asus Tuf Wireless
Net
Fibra Tim 100mb
OS
Windows 10 Pro 64 bit
si è similare però è piu performante dell if else
 
M

Mursey

Ospite
La variabile accumulatore non mi sembra che accumuli ma che contenga solo l'ultimo valore, ho visto bene ?
E' una cosa voluta ?
 
  • Mi piace
Reazioni: Fab996

Fab996

Utente Attivo
177
5
La variabile accumulatore non mi sembra che accumuli ma che contenga solo l'ultimo valore, ho visto bene ?
E' una cosa voluta ?

Inizialmente l'avevo pensata come accumulatore per salvare il risultato precedente, poi però a fine applicazione contiene solo l'ultimo valore in quanto viene sempre reimpostata a 0

- - - Updated - - -

si è similare però è piu performante dell if else
Però da quanto ho capito lo switch-case posso utilizzarlo solo con tipi primitivi...
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Lo switch-case puoi utilizzarlo con tipi primiti e con oggetti di tipo String.
 
  • Mi piace
Reazioni: Fab996

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Volevo chiedere qualche consiglio su come poter migliorare il codice
Più che altro la calcolatrice funziona solo non capisco perchè se eseguo in sequenza operazioni di moltiplicazione e divisione(sfruttando la proprietà associativa) non funziona bene tipo 6*4*2=48 per le moltiplicazioni e divisioni devo fare le operazioni due a due(per esempio 6*4 poi premere uguale = 24 e poi moltiplicare 24 per 2, e quindi non posso fare direttamente 6*4*2=48, mentre con addizione e sottrazione si), poi non capisco perchè se eseguo 3+2*5=13 non funziona bene...

Le calcolatrici si comportano diversamente. Se provi ad aprire quella che hai sul pc, noterai che quasi certamente dopo alla prima moltiplicazione, come 6*4, viene mostrato il risultato direttamente; non avviene ciò solo se hai un'addizione seguita da una moltiplicazione (o divisione), come nella tua seconda operazione.

Comunque le calcolatrici di solito usano uno stack o due (uno per i valori ed uno per le operazioni). Inoltre un'operazione come "3+2*5" verrebbe letta dal tuo software senza dare la precedenza agli operatori * e /. Quindi l'errore di cui parli, sicuramente si riferisce al fatto che come risultato ottieni 25 alla seconda operazione che hai mostrato. Il software non sa che dopo ci sarà una moltiplicazione. Se noti le calcolatrici "reali", quando premi ad esempio la moltiplicazione, come nel caso della tua seconda operazione, non eseguono la somma precedente subito, come fanno con le addizioni.


Inoltre nel main posso fare Calcolatrice c = new Calcolatrice(); ma anche JFrame c = new Calcolatrice(); per il polimorfismo?

Si, puoi. Anche se in questo caso non ti serve a molto.

Inoltre non capisco perchè nel costruttore Calcolatrice(), posso fare ActionListener asc = new Event(this); come parametro gli passo l'oggetto corrente, ossia la calcolatrice per inizializzare il listener in quanto deve poter accedere alla mia applicazione, ma non capisco perchè Event sia di tipo ActionListener...

Event è di tipo ActionListener perchè implementi ActionListener. Il polimorfismo si applica anche alle interfacce comunque. E' qui che forse ne vedrai delle belle. ;)
 
  • Mi piace
Reazioni: Mursey e Fab996

Fab996

Utente Attivo
177
5
Event è di tipo ActionListener perchè implementi ActionListener. Il polimorfismo si applica anche alle interfacce comunque. E' qui che forse ne vedrai delle belle. ;)
Non sapevo che il polimorfismo si applicasse anche alle interfacce, anche perchè non lo trovo scritto in maniera esplicita da nessuna parte...

Poi non ho capito la vera utilità di estendere la classe Calcolatrice con JFrame, l'unica differenza è che estendendo JFrame posso applicare tutti i metodi di JFrame direttamente alla Calcolatrice, però potrei anche non estenderla e fare un metodo main che invece di inizializzare la calcolatrice inizializza JFrame...
Inoltre mi è venuto un dubbio riguardo i metodi static/non static, i non static sono metodi d'istanza e quindi presuppongono che ci sia un oggetto su cui chiamarli, mentre quelli non static non possono accedere alle variabili d'istanza e si chiamano nomeclasse.metodo(); però non capisco quando usare uno e quando usare l'altro, per esempio nella classe Punto:
Codice:
class Punto{
private double x;
private doube y;
public Punto(doube xx; double yy) {
this.x = xx;
this.y = yy;
}
public double getx() {
return x;
}
public double gety(){
return y;
}
public static double distanza(Punto p1, Punto p2) {
return Math.sqrt(Math.pow(p2.getx()-p1.getx(),2)+Math.pow(p2.gety()-p1.gety())
}
}
Il metodo distanza la mia prof l'aveva fatto static, solo io l'avevo fatto anche non static, non capisco quando bisogna veramente usare un metodo static e quando uno non static, per esempio solitamente in tutte le classi che mi sono capitate in cui c'era il main facevo sempre metodi static..
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
Non sapevo che il polimorfismo si applicasse anche alle interfacce, anche perchè non lo trovo scritto in maniera esplicita da nessuna parte...

Poi non ho capito la vera utilità di estendere la classe Calcolatrice con JFrame, l'unica differenza è che estendendo JFrame posso applicare tutti i metodi di JFrame direttamente alla Calcolatrice, però potrei anche non estenderla e fare un metodo main che invece di inizializzare la calcolatrice inizializza JFrame...

Fatto in quel modo sarebbe difficile da gestire, in quanto dovresti come minimo passare il JFrame ad una classe Calcolatrice che poi aggiungerà su esso i componenti. Di solito gli approcci sono o quello che hai usato tu, ovvero estendere JFrame, oppure creare una classe ed al suo interno creare un oggetto JFrame. Quest'ultimo lo trovo più flessibile da gestire, ma anche l'altro non è scorretto.
In entrambi i casi stai creando una gerarchia. Nel caso dell'extends stai però dicendo che Calcolatrice è un JFrame; nel secondo caso invece che ha un JFrame (e concettualmente non sono la stessa cosa).


Inoltre mi è venuto un dubbio riguardo i metodi static/non static, i non static sono metodi d'istanza e quindi presuppongono che ci sia un oggetto su cui chiamarli, mentre quelli non static non possono accedere alle variabili d'istanza e si chiamano nomeclasse.metodo(); però non capisco quando usare uno e quando usare l'altro, per esempio nella classe Punto:

Codice:
class Punto{
private double x;
private doube y;
public Punto(doube xx; double yy) {
this.x = xx;
this.y = yy;
}
public double getx() {
return x;
}
public double gety(){
return y;
}
public static double distanza(Punto p1, Punto p2) {
return Math.sqrt(Math.pow(p2.getx()-p1.getx(),2)+Math.pow(p2.gety()-p1.gety())
}
}
Il metodo distanza la mia prof l'aveva fatto static, solo io l'avevo fatto anche non static, non capisco quando bisogna veramente usare un metodo static e quando uno non static, per esempio solitamente in tutte le classi che mi sono capitate in cui c'era il main facevo sempre metodi static..


Le classi che contengono metodi statici sono di norma "classi di utilità", diciamo così. Sono quel tipo di classi che hanno delle funzionalità generiche e delle quali non si necessita di un oggetto per poter utilizzare i metodi. Se vuoi conoscere la radice quadrata di un numero, richiami direttamente la funzione, non serve creare istanze, non ci sono altre elaborazioni da eseguire. Quel dato lo utilizzi una volta, non devi svolgere altre elaborazioni con quei numeri.

Nel caso della classe Punto dipende dal design, le implementazioni possono variare.
Nelle classi in cui c'è il main devi fare metodi statici, è diverso. Non puoi avere un metodo non statico, ma la colpa è del metodo statico main(). Ci sono delle restrizioni e delle regole rigide con questo tipo di metodi. Per definizione un metodo "non statico" è un metodo che viene chiamato sull'istanza di una classe. Un metodo static invece no, non necessita di un oggetto.
Per invocare un metodo statico devi usare il nome della classe che lo contiene (come si fa con Math).
 
  • Mi piace
Reazioni: Fab996

Fab996

Utente Attivo
177
5
Nelle classi in cui c'è il main devi fare metodi statici, è diverso. Non puoi avere un metodo non statico, ma la colpa è del metodo statico main(). Ci sono delle restrizioni e delle regole rigide con questo tipo di metodi.

Non capisco perchè non posso avere un metodo non statico in una classe con il main, tipo questo è il codice per calcolare il massimo in un array

Codice:
import java.util.*;class MassimoArray {
    public static void main(String[] args) {
        int[] numeri;
        int i,e;
        Scanner sc = new Scanner(System.in);
        numeri = new int[10];
        for (i=0; i<numeri.length; i++)
            numeri[i] = sc.nextInt();
        e = massimo(numeri);
        System.out.println("Il massimo numero all'interno dell'array è "+e);
    }
    public static int massimo(int[] a) {
        int s,z;
        s= a[0];
        for (z=1; z<a.length; z++) {
            if(s<a[z])
                s=a[z];
        }
        return s;
    }
}
Non potevo anche riscriverlo in questo modo:
Codice:
import java.util.*;
class MassimoArray {
    public static void main(String[] args) {
        int[] numeri;
        int i,e;
        Scanner sc = new Scanner(System.in);
        numeri = new int[10];
        for (i=0; i<numeri.length; i++)
            numeri[i] = sc.nextInt();
        e = numeri.massimo();
        System.out.println("Il massimo numero all'interno dell'array è "+e);
    }
    public int massimo() {
        int s,z;
        s= this[0];
        for (z=1; z<this.length; z++) {
            if(s<this[z])
                s=this[z];
        }
        return s;
    }
}
In questo modo è un metodo non statico e il this punta all'oggetto corrente, ossia all'array numeri, dato che il metodo massimo è stato chiamato su di esso
 

DispatchCode

Moderatore
Staff Forum
Utente Èlite
2,223
1,854
CPU
Intel I9-10900KF 3.75GHz 10x 125W
Dissipatore
Gigabyte Aorus Waterforce X360 ARGB
Scheda Madre
Asus 1200 TUF Z590-Plus Gaming ATX DDR4
HDD
1TB NVMe PCI 3.0 x4, 1TB 7200rpm 64MB SATA3
RAM
DDR4 32GB 3600MHz CL18 ARGB
GPU
Nvidia RTX 3080 10GB DDR6
Audio
Integrata 7.1 HD audio
Monitor
LG 34GN850
PSU
Gigabyte P850PM
Case
Phanteks Enthoo Evolv X ARGB
Periferiche
MSI Vigor GK30, mouse Logitech
Net
FTTH Aruba, 1Gb (effettivi: ~950Mb / ~480Mb)
OS
Windows 10 64bit / OpenSUSE Tumbleweed
No, non puoi riscriverlo in quel modo.

Mi devo essere espresso male: da un metodo static hai due scelte: o richiamare un altro metodo static, o creare un oggetto e richiamare poi sull'oggetto il metodo non statico. La motivazione è quella del post precedente:

[...]Per definizione un metodo "non statico" è un metodo che viene chiamato sull'istanza di una classe. Un metodo static invece no, non necessita di un oggetto. [...]

Un metodo che non è statico può essere richiamato creando un oggetto.


Il secondo codice che hai mostrato ha molte cose che non vanno. Una è ad esempio:

Codice:
e = numeri.massimo();

numeri è un'array di interi. Non esiste il metodo massimo(). Il metodo massimo si trova nella classe MassimoArray e per richiamarlo devi creare un'istanza di MassimoArray.

Cose come questa inoltre:

Codice:
        s= this[0];
        for (z=1; z<this.length; z++) {
            if(s<this[z])
                s=this[z];

non hanno alcun significato. Non esiste un accesso a this[0], non è un'array. Ed inoltre non avendo creando un oggetto non hai appunto istanze... non sei all'interno di un oggetto. Se vuoi richiamare massimo() devi creare un oggetto; oppure dichiarare il metodo static. E' una limitazione dovuta, come dicevo sopra, al fatto che il metodo statico viene chiamato senza alcun bisogno di creare istanze; ergo se vuoi accedere ai membri di una classe non statici, dovrai usare un oggetto.
 
  • Mi piace
Reazioni: Fab996

Fab996

Utente Attivo
177
5
Grazie mille, ho capito :D
Una curiosità, perchè il prototipo di un costruttore non ha il tipo di ritorno? Cioè alla fine il costruttore è solamente un metodo...
 

BAT

Moderatore
Staff Forum
Utente Èlite
22,944
11,580
CPU
1-Neurone
Dissipatore
Ventaglio
RAM
Scarsa
Net
Segnali di fumo
OS
Windows 10000 BUG
Una curiosità, perchè il prototipo di un costruttore non ha il tipo di ritorno? Cioè alla fine il costruttore è solamente un metodo...
Perché un costruttore non è affatto un metodo:
un costruttore crea ed inizializza in memoria oggetti che ancora non esistono, mentre un metodo è una procedura che funziona su oggetti che devono esistere (altrimenti come minimo hai un NullPointerException).
E poiché un costruttore crea un oggetto di una specifica classe (infatti un costruttore ha lo stesso nome della classe), il "tipo" di ritorno è implicito (la classe stessa) senza che ci sia bisogno del return, invece un metodo DEVE avere per forza un tipo di ritorno (che può essere qualsiasi, compreso il void)
Che un costruttore NON sia un metodo è anche evidente nella sintassi:
per costruire un oggetto di una certa classe il costruttore si invoca con new NomeClasse(parametri)
invece un metodo lo chiami con la sintassi oggetto.nomeMetodo(parametri)
 
Ultima modifica:
  • Mi piace
Reazioni: _Gemba_ e Fab996

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!