Klasa wew czy zew.

0

tutaj przykład z klasa zewnętrzna

import javax.swing.*;
import java.awt.*;

public class proba{
    JButton przycisk;
    JFrame ramka;

    public static void main(String[] args)
    {
        proba p = new proba();
        p.run();
    }

    public void run(){
        przycisk = new JButton("ala ma kota");
        ramka = new JFrame();

        ramka.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        przycisk.addActionListener(new proba2(przycisk));

        ramka.add(BorderLayout.SOUTH, przycisk);

        ramka.setSize(200,200);
        ramka.setVisible(true);
    }
}


import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class proba2 implements ActionListener {

    private JButton przycisk;
    public void actionPerformed(ActionEvent zdarzenie) {
        przycisk.setText("wcisniety");
    }
    public proba2(JButton p){
        przycisk = p;
    }
}

a tutaj z wew

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class proba{
    JButton przycisk;
    JFrame ramka;

    public static void main(String[] args)
    {
        proba p = new proba();
        p.run();
    }

    public void run(){
        przycisk = new JButton("ala ma kota");
        ramka = new JFrame();

        ramka.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        przycisk.addActionListener(new wew());

        ramka.add(BorderLayout.SOUTH, przycisk);

        ramka.setSize(200,200);
        ramka.setVisible(true);
    }

    class wew implements ActionListener{
        public void actionPerformed(ActionEvent zdarzenie) {
               przycisk.setText("wcisniety");
        }
    }
}

Moje pytanie jest takie, które lepiej stosować? Czy w jednej klasie robić kilka klas (jak będzie kilka buttonów) czy klasy wyodrębnić na zewnątrz?

Ja myślę tak. Jeżeli te klasy tylko reagują na dane eventy to niech zostaną jako wewnętrzne, ale jeśli mają już np jakiś stan to wtedy niech będą zewnętrzne. Ale nie jestem pewien czy będzie to dobra praktyka.

1

Najpierw musisz sobie uzmysłowić różnice pomiędzy typami klas.

Mamy takie rodzaje:

  • Klasy zwykłe,
  • Klasy wewnętrzne,

Klasy wewnętrzne dzielą się na:

  • Klasy wewnętrzne statyczne,
  • Klasy wewnętrzne niestatyczne,

Klasy wewnętrzne niestatyczne dzielą się na:

  • Klasy anonimowe,
  • Klasy wewnętrzne niestatyczne nieanonimowe,

Największa różnica między klasami zwykłymi, a wewnętrznymi, oprócz ilości kodu/ czytelności/ etc to widoczność pól - klasa wewnętrzna ma dostęp do większej ilości pól.

Największa różnica między klasami wewnętrznymi statycznymi, a klasami wewnętrznymi niestatycznymi jest taka, że klasy wewnętrzne niestatyczne mają implicite wskaźnik do obiektu klasy otaczającej. Ten wskaźnik daje bezpośredni dostęp do pól obiektu klasy otaczającej. Może być też powodem wycieku pamięci, np jeśli tworzysz obiekt klasy wewnętrznej niestatycznej, który nie korzysta z pól obiektu klasy otaczającej, a obiekt klasy otaczającej staje się niepotrzebny. I właśnie ta możliwość wycieku (czyli tutaj trzymania referencji do obiektów nieużywanych) jest głównym powodem, by się zastanowić czy użyć klasy wewnętrznej niestatycznej. Oczywiście nawet bez klas wewnętrznych niestatycznych może dojść do tego samego typu wycieku, no ale klasy wewnętrzne niestatyczne mają implicite referencję, czyli taką, której na pierwszy rzut oka nie widać.

Reasumując:

  • jeśli chcemy stworzyć klasę dla obiektów, które będą przez całe życie powiązane z obiektem matką (np konkretny listener dla konkretnego okna), to dobrze użyć klas wewnętrznych niestatycznych,
  • w pozostałych przypadkach lepiej raczej zastosować klasy wewnętrzne statyczne lub klasy zwykłe,
1

Ja zazwyczaj stosuję taką zasadę: Jeżeli akcja musi mieć dostęp do inny komponentów, a nie tylko do źródła zdarzenia, to robię klasę wewnętrzną, żeby niczego nie przekazywać. W Twoim pierwszym przykładzie (z klasą zewnętrzną) nie trzeba niczego przekazywać do klasy proba2.

import javax.swing.*;
import java.awt.*;
 
public class proba{
    JButton przycisk;
    JFrame ramka;
 
    public static void main(String[] args)
    {
        proba p = new proba();
        p.run();
    }
 
    public void run(){
        przycisk = new JButton("ala ma kota");
        ramka = new JFrame();
 
        ramka.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 
        przycisk.addActionListener(new proba2());
 
        ramka.add(BorderLayout.SOUTH, przycisk);
 
        ramka.setSize(200,200);
        ramka.setLocationRelativeTo(null); //centruje okno
        ramka.setVisible(true);
    }

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class proba2 implements ActionListener {
    public void actionPerformed(ActionEvent zdarzenie) {
        ((JButton)zdarzenie.getSource()).setText("wcisniety");
    }
}

}