Vererbung Übergabe von Variablen der Superklasse an Subklasse mit "extends"

Abend die Leute 🙂

Nachdem ich seit gestern nicht kapiere, was ich mit der Vererbung falsch mache, dachte ich mir, ich poste einfach mal mein Problem hier ...

Ich möchte in der Klasse hbS_ActionListener mit den Objekten (bzw. das JLabel display), die ich in der Klasse hbS erstellt habe, arbeiten können, also "display.setText()" verwenden können.

Und dafür muss ich ja, hbS zur Superklasse machen, und das funktioniert mit dem Schlüsselworte "extends" oder nicht ?

Naja, erstmal die beiden Klassen:

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

public class hbS extends JFrame
{ 
  private JLabel[] l = new JLabel[2];
  private JList roomList = new JList();
  private JList smokeList = new JList();
  private JList priceList = new JList();
  private JButton start = new JButton();
  public JLabel display = new JLabel();
  
  public static void main(String[] args)
  {
    hbS frame = new hbS("Hotelbuchungssystem");
    frame.setVisible(true);
  }
  
  public hbS(String title)
  {
    //Erstellen des Fensters
    super(title);
    setBounds(100,100,400,500);
    setLayout(null);
     
    [...]

    //Erstellen des Button zum Starten der Suche nach verfügbaren Zimmern
    start = new JButton("Suchen");
    start.setBounds(20,150,90,30);
    add(start);
    start.setActionCommand("start");
    //actionPerformed() ausgelagert in Objekt hbS_ActionListener() zur Übersichtlichkeit
    start.addActionListener(new hbS_ActionListener());
    
    //Estellen des Textfeldes, in dem die Suchergebnisse gelistet werden
    display = new JLabel();
    display.setBounds(20,170,300,300);
    display.setText("<html><body>Textzeile1<br>Textzeile2</body></html>");
    add(display);  
  }
}

Java:
import java.awt.event.*;
import java.io.*;

public class hbS_ActionListener extends hbS implements ActionListener
{ 
  public void actionPerformed(ActionEvent eve)
  {
    if (eve.getActionCommand().equals("start")) 
    {
      try 
      { 
        //Erstellen eines Objekts vom Typ hbS_getFileData um Methoden auslagern zu können und Code übersichtlicher zu machen
        hbS_getFileData obj = new hbS_getFileData();
        //Übergeben der Daten in der Textdatei
        String[] data = obj.readFile("hotbooksys.txt");
        
        [...]

        //Suche, welche Räume überhaupt frei sind
        int[] emptyRooms = obj2.getEmptyRooms(dataList);
        obj2.displayEmptyRooms(emptyRooms);
        
       //display.setText(" "); <--- das möchte ich machen können !

      }  
      catch(IOException err) 
      {
        System.out.print("***FEHLER BEIM EINLESEN DER DATEI***");
      }
      
    } // end of if
  }
}

Bekomme diese Fehlermeldung, welche ich auch verstehe, da sie sich auf die Methode hbS(String title) bezieht. Aber ich möchte doch die ganze Klasse vererben, was will er mit der Methode?

Java:
hbS_ActionListener.java:4:8: error: constructor hbS in class hbS cannot be applied to given types;
public class hbS_ActionListener extends hbS implements ActionListener
       ^
  required: String
  found: no arguments
  reason: actual and formal argument lists differ in length
1 error

Habe gelesen, ich muss irgendwas mit super() machen. Aber was ? Hab schon so einiges ausprobiert, und hatte schon einige Beispiele mir angeschaut, aber übertragen auf meinen Code, funktionierte es nicht.

Wäre über eine kurze Hilfe sehr dankbar ! 🙂
 
Zuletzt bearbeitet:
Guten Abend,

der Fehler der bei dir auftritt ist dadurch zu erklären, dass du in hbS ja den hbS_ActionListener mit

new hbS_ActionListener() erzeugst. Durch das extends übernimmst du auch die Konstruktoren der Oberklasse. Dieser erwartet einen String. Einen Parameterlosen Konstruktor hat der ActionListener damit nicht mehr, folglich kann das schon nichts mehr werden.

Aber generell ist deine Vorgehensweise nicht zu empfehlen. Der ActionListener ist ja kein hbS, also kein Fenster, sondern nur ein Listener. Die Vererbung macht aus fachlicher Sicht keinen Sinn. Programmier mal eine get-Methode für das Label, danach schaust du dir mal das Singleton-Entwurfsmuster an.
 
Ja stimmt, der ActionListener hat ja eigentlich nichts mit dem Fenster hbS zu tun ...

Aber die eigene Klasse für den Listener an sich macht schon Sinn, oder ? Also dass alles schön voneinander getrennt ist...

Hab jetzt getText() so gemacht :

Java:
import java.awt.event.*;
import java.io.*;

public class hbS_ActionListener implements ActionListener
{ 
  String text;
  
  public void actionPerformed(ActionEvent eve)
  {
    if (eve.getActionCommand().equals("start")) 
    {
      try 
      { 
        [...]
        i = 0;
        text = "" + emptyRooms[i];
        text = getString(emptyRooms, text, i);
        
        System.out.println(text);
        
      }  
      catch(IOException err) 
      {
        System.out.println("***FEHLER BEIM EINLESEN DER DATEI***");
      }
      
    } // end of if
  }
  public String getString(int[] emptyRooms, String text, int i)
  {
    i++;
    if (i<emptyRooms.length) 
    {
      text = text + " " + emptyRooms[i];
      text = getString(emptyRooms, text, i);
    } // end of if
    
    return text;
    
  }
  
  public String getText()
  {
    return text;  
  }
}

und in hbS eben ein Objekt der ActionListener-Klasse erstellt, damit das Label display drauf zugreifen kann

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


public class hbS extends JFrame
{
  [...]
  public static void main(String[] args)
  {
    hbS frame = new hbS("Hotelbuchungssystem");
    frame.setVisible(true);
  }
  
  public hbS(String title)
  {
    [...]
    //Erstellen des Textfeldes, in dem die Suchergebnisse gelistet werden
    display = new JLabel();
    display.setBounds(20,170,300,300);
    display.setText("<html><body>Textzeile1<br>Textzeile2</body></html>");
    hbS_ActionListener obj = new hbS_ActionListener();
    display.setText(obj.getText());
    add(display);
    
  }
}

aber hab schon von vornherein gemerkt, dass da was nicht funktionieren wird.

Die display.setText(obj.getText()) - Zeile wird ja nur einmal aufgerufen, und zwar während das Fenster gezeichnet wird. Ergo, steht nichts in display. Wenn ich auf den Start-Knopf drücke, wird die Zeile ja nicht aufgerufen ... also wäre ich wieder am Anfang, dass ich den ActionListener dazu bringen muss, display verändern zu können ...

oder hat genau dieses Problem jetzt was mit dem Singleton-Entwurfsmuster zu tun, und deshalb soll ich es mir anschauen ?

Frage nur, dass ich dann weiß, dass mein Ansatz bis jetzt richtig ist (und von dir so gedacht war) 🙂 Dann würde ich mich in das Entwurfsmuster einlesen.
 
Zuletzt bearbeitet:
Inwieweit dich das Singleton-Pattern hier weiter bringen soll, entzieht sich meiner Kenntnis.
Aber um den ActionListener Zugriff auf das JLabel zugeben, kannst du es z. B. einfach im Konstruktor übergeben:
Java:
public class TextChanger implements ActionListener{
    private JLabel display;
    TextChanger(JLabel display){
        this.display = display;
    }
    public void actionPerformed(ActionEvent eve){
        //blabla
        display.setText(getString(emptyRooms, text, i));
    }
}
public class HotelBookingSystem extends JFrame
{
  [...]
  public static void main(String[] args)
  {
    HotelBookingSystem frame = new HotelBookingSystem("Hotelbuchungssystem");
    frame.setVisible(true);
  }
 
  public HotelBookingSystem(String title)
  {
    [...]
    //Erstellen des Textfeldes, in dem die Suchergebnisse gelistet werden
    display = new JLabel();
    hbS_ActionListener obj = new hbS_ActionListener(display);
    add(display);
   
  }
}
Klassennamen beginnen in Java mit einem Grossbuchstaben und sollten sprechend sein!
 
Zuletzt bearbeitet:
Das Singleton-Pattern kann hier genutzt werden um an das Feld zu kommen. Ich habe das hier empfohlen, da es leicht umzusetzen ist. Das übergeben per Konstruktor ist natürlich noch einfacher, darauf bin ich nur irgendwie nicht gekommen 😀

Die "non-plus-ultra"-Version wäre aus meiner Sicht das MVC-Pattern...

EDIT: Bei der Größe des Programmes aber aktuell natürlich totaler "overkill"
 
Zuletzt bearbeitet:
So, vielen Dank an euch beide 🙂 Klappt jetzt so wie ich es will 🙂

Hab mein Problem jetzt so gelöst, sodass ich sozusagen zwei essentielle Funktionen des Programms in einer Zeile stehen habe - den Suchen-Knopf, sowie JLabel display dem Listener hinzuzufügen (zuzu ? 😀)

Java:
//Erstellen des Textfeldes, in dem die Suchergebnisse gelistet werden
    display = new JLabel();    
    display.setBounds(20,170,300,300);
    display.setText("<html><body>Textzeile1<br>Textzeile2</body></html>");
    start.addActionListener(new HBS_ActionListener(display));
    add(display)
 

Zurück
Oben