Material‎ > ‎

Innere Klassen (Beispiele)

JButtonDemo.java


Ein Knopf in einer graphischen Anwendung muss irgendwie mitteilen, dass der Knopf gedrückt worden ist.  Dies wird mittels eines Methodenaufrufes getan.  Welche Methode aufgerufen wird, wird durch den Aufruf button.addActionListener mitgeteilt.  Im einfachsten Falle rufen wir einfach eine Methode in derselben Klasse auf, in der auch die Benutzeroberfläche selbst implementiert ist.  Der Methodenname ist durch das ActionListener Interface festgelegt und heißt actionPerformed.  Wir nennen solche Methoden einen Callback.

In diesem Programm löst das Drücken des Knopfes das Zählen in der Variable count aus.

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


public class JButtonDemo extends JFrame implements ActionListener {
    int count = 0;

    public JButtonDemo() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton button = new JButton("Press Me");
        add(button,BorderLayout.CENTER);
        button.addActionListener(this);
        setSize(300,150);
        setVisible(true);
    }

    // what if we have multiple buttons?
    public void actionPerformed(ActionEvent e) {
        count++;
        System.out.println("count = "+count);
    }

    public static void main(String[] args) {
        JFrame frame = new JButtonDemo();
    }
}


JButtonDemo1.java


Die vorhergehende Methode ist nicht sonderlich flexibel, da nur eine Methode actionPerformed definiert werden kann; wenn es mehrere Knöpfe gäbe, würde es schwer sein, diese zu unterscheiden.  Deswegen führt man ein neues Objekt ein, hier MyAction genannt.  In der ersten Version ist das eine statische Klasse.  Um die Variable count zu verändern muss diese statische Klasse explizit eine Referenz auf das Objekt enthalten, dass den Zähler tatsächlich enthält.  Der Bezug auf count in MyAction muss daher explizit über target.count durchgeführt werden.

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


public class JButtonDemo1 extends JFrame {
    int count = 0;

    static class MyAction implements ActionListener {
        JButtonDemo1 target;
        public MyAction(JButtonDemo1 t) {
            target = t;
        }
        public void actionPerformed(ActionEvent e) {
            target.count++;
            System.out.println("count = "+target.count);
        }
    }

    public JButtonDemo1() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton button = new JButton("Press Me");
        add(button,BorderLayout.CENTER);
        button.addActionListener(new MyAction(this));
        setSize(300,150);
        setVisible(true);
    }

    public static void main(String[] args) {
        JFrame frame = new JButtonDemo1();
    }
}


JButtonDemo2.java


Die manuelle Übergabe der Zielklasse ist etwas umständlich.  Um dies zu vermeiden hat Java das Konzept einer inneren Klasse.  Diese Version ist ganz analog zur vorherigen, wir vermeiden aber den expliziten Gebrauch von target; stattdessen kann auf count aus der inneren Klasse direkt zugegriffen werden.


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


public class JButtonDemo2 extends JFrame {
    int count = 0;

    class MyAction implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            count++;
            System.out.println("count = "+count);
        }
    }

    public JButtonDemo2() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton button = new JButton("Press Me");
        add(button,BorderLayout.CENTER);
        button.addActionListener(new MyAction());
        setSize(300,150);
        setVisible(true);
    }

    public static void main(String[] args) {
        JFrame frame = new JButtonDemo2();
    }
}


JButtonDemo3.java

Diese Version verwendet anonyme innere Klassen.  Mit diesen ist es nicht einmal mehr notwendig, eine explizite Klasse zu definieren.


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


public class JButtonDemo3 extends JFrame {
    int count = 0;

    public JButtonDemo3() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton button = new JButton("Press Me");
        add(button,BorderLayout.CENTER);
        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                count++;
                System.out.println("count = "+count);
            }
        });
        setSize(300,150);
        setVisible(true);
    }

    public static void main(String[] args) {
        JFrame frame = new JButtonDemo3();
    }
}


JButtonDemo4.py


In anderen Programmiersprachen ist die Benennung einer Callback-Methode wesentlich einfacher: anstatt komplizierte Konzepte, wie innere oder anonyme Klassen zu verwenden, können wir den Methodennamen einfach direkt verwenden.  Wenn wir mehrere Knöpfe mit mehreren Callbacks hätten, könnten wir diese durch mehrere Methoden behandeln lassen.  Dieser Ansatz wird in C# und Python verwendet.

Beachte allerdings, dass self.pressed nicht nur den Methodennamen enthält, sondern auch das Objekt, auf das diese Methode angewandt werden soll; wir nennen solche Methoden "gebundene Methoden".

import gtk

class ButtonDemo:

    def __init__(self):
        self.count = 0
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_geometry_hints(min_width=300,min_height=150)
        self.button = gtk.Button("Press Me")
        self.window.add(self.button)
        self.button.connect("clicked",self.pressed)
        self.window.show_all()

    def pressed(self,*args):
        self.count += 1
        print "count =",self.count

demo = ButtonDemo()
gtk.main()


ċ
JButtonDemo.java
(1k)
Ludwig Schmidt-Hackenberg,
03.02.2011, 07:52
ċ
JButtonDemo1.java
(1k)
Ludwig Schmidt-Hackenberg,
03.02.2011, 07:52
ċ
JButtonDemo2.java
(1k)
Ludwig Schmidt-Hackenberg,
03.02.2011, 07:52
ċ
JButtonDemo3.java
(1k)
Ludwig Schmidt-Hackenberg,
03.02.2011, 07:53
ċ
JButtonDemo4.py
(0k)
Ludwig Schmidt-Hackenberg,
03.02.2011, 07:52
Comments