Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
ich würde gerne wissen, welche Vorteile das erben von der Klasse JFrame hat.
Persönlich schöner finde ich es nämlich, wenn man ein JFrame erzeugt und diesem dann die Komponenten hinzufügt.
Was meint ihr bzw. wie macht ihr es?
In meiner Schulzeit wurde auch immer davon abgeraten von JFrame zu erben..
Der alte Prof. hatte aber die Eigenart dann die Klasse von JPanel (=mainpanel) erben zu lassen und dort halt dann drauf die Komponenten zu adden und das ganze dann aufs JFrame..
Ob das jetzt soviel mehr Sinn hatte.. Man könnte halt in die paint-Methoden oder sonstigen eingreifen, aber tjo.. Wenn mans nicht braucht, hats nicht wirklich Vorteile..
Vielen Dank für die schnellen Einschätzungen.
Habe hier nämlich gerade ein Buch vor mir liegen, wo das so gemacht wird. Aber dann möchte ich mir das gar nicht erst angewöhnen.
Klar, du kannst nur von einer Klasse erben. Wenn du also schon von JFrame erbst hast du keine Möglichkeit mehr von ner anderen Klasse zu erben.
Man sollte imho Komposition immer der Vererbung vorziehen, falls man nicht unbedingt das Verhalten der Klasse ändern bzw. erweitern will.
Von JFrame erben macht mMn nie sinn. Von JPanel eigentlich nur wenn man die paintComponent Methode überschreiben will.
wer will schon je in einer JFrame-Klasse von etwas anderem erben?
oder selbst wenn ist es immer leicht umzubauen und spätestens bei der zweiten Vererbung hätte man dasselbe Problem, nix gewonnen,
zweimal Vererbung klingt komisch? genauso auch nur eine Vererbung bei JFrame..
das ist bisschen unsauber aber einfach nur eine Kleinigkeit, macht 1-x frame.xy()-Aufrufe leichter,
JFrames hat man üblicherweise nur 1x oder wenn dann je JFrame eine Klasse die sich darum kümmert, die nach außen gerne auch wie ein JFrame aussehen darf um z.B. setVisible(true) aufzurufen,
genauso mehrere JPanel-Klassen für größere Sub-Strukturen
Java:
SubPanelXy a = new SubPanelXy();
add(a);
schreibt sich schöner als
Java:
SubPanelXy a = new SubPanelXy();
this.frame.add(a.getPanel());
immer eine Gratwanderung, an anderen Stellen würde ich auch nicht etwa von ArrayList erben,
aber in GUIs ist das schon ziemlich handlich und übersichtlich
Vielleicht kann man das Risiko, Methoden versehentlich zu überschreiben, als Nachteil sehen.
Und: Wie ist das mit Threads? Wenn JFrame nicht threadsicher ist, wie ist es dann mit Threads, die in dem Objekt erzeugt werden? (Vielleicht offenbart die Fragestellung schon, dass ich mich damit nicht auskenne, is nur so'n Gedanke ^^ )
im Grunde exakt dasselbe aus meiner Sicht, wobei ich persönlich so gut wie nie irgendeine Thread-Methode brauche, dann geht Runnable,
wenn man aber interrupt(), join(), isAlive() usw. abfragen will und eine Klasse hat die 'für diesen Thread' steht, also normalerweise eh von nichts zu erben hat, dann könnte diese von Thread erben, statt den Thread extra in einem Attribut stehen zu haben
Die Frage nach Threads ist eigentlich orthogonal dazu. Ein "hartes" Gegenargument kann ich spontan nicht nennen, aber ... was sollte in einer Klasse stehen, damit sie von JFrame erben muss? Oder damit es einen Vorteil bringt? Für welches "X" gilt "X ist ein JFrame"?
Grenzfälle könnte es geben, wenn man z.B. eine komplizierte Toolbar einbauen will oder viel mit anderen JFrame-eigenen Methoden rumhantiert oder so, aber auch das ist kein echter Grund. Und wenn es keinen driftigen Grund gibt, sollte man nicht Vererben.
Ehe Swing eingeführt wurde, machte es keinen Sinn von "Frame" zu erben. Jetzt erbt "JFrame" von "Frame" und inzwischen sogar "JXFrame" von "JFrame" (SwingX library). Es macht offenbar nur Sinn, wenn Du eine grundlegende und allgemein gültige Idee hast, wie Du einen Frame noch intelligenter machen kannst als eine bestehende Klasse.
wozu wird überhaupt ein Objekt der Klasse HalloWelt erstellt, könnten doch alle Befehle in der main-Methode stehen..
das letzte Programm auf der Seite zeigt, wie 3/4 der Befehle ohne die Vererbung noch komplizierter wären
Java:
public class HalloWelt extends JFrame{
JLabel schriftZug;
public HalloWelt(String titel){
super(titel); // *, ok, super ist vielleicht noch ungewöhlicher als JFrame-Konstruktor-Aufruf
setDefaultCloseOperation(EXIT_ON_CLOSE); // *, 2x, auch für die Konstante
setSize(300, 300); // *
Container cp = getContentPane(); // *
cp.setLayout(new BorderLayout());
schriftZug = new JLabel("HalloWelt");
cp.add(schriftZug,BorderLayout.NORTH); // *
setVisible(true); // *
}
public static void main(String[] args){
new HalloWelt("Ich bin ein JFrame-Objekt");
}
}
Also meinst Du, dass es hier sinnvoll von JFrame zu erben, da die Befehle sonst komplizierter wären oder hast Du dich unglücklich ausgedrück und/oder ich dich missverstanden?
meine Meinung stand im Posting von 15:37: nicht notwendig, "aber in GUIs ist das schon ziemlich handlich und übersichtlich",
wenn ich mich zu "sinnvoll" ja oder nein entscheiden muss: ja
und wenn man die paintComponent eines JPanels überschreibt, dann ist es ok?
dann nutzt man gleich eine eigene Klasse auch für Aufrufe wie setBackground(), setPreferredSize() usw?
das ist doch auch nicht konsequent, dort könnte man doch genauso ein JPanel-Attribut verwenden:
Java:
class CompPanel {
JPanel p;
p.add(..);
p.add(..);
}
class PaintPanel {
JPanel p = new JPanel() {
paintCompoent() {
...
}
};
p.set(..);
}
dagegen finde ich Erben in beiden Fällen ehrlicher und einheitlicher
Wenn man das Verhalten einer bestehenden Klasse ändern will, kommt man oft um eine Erweiterung durch Vererbung nicht herum. Letztlich wird ja in Deinem Beispiel ebenfalls ein JPanel durch eine anonyme Klasse erweitert .
stimme Andre zu. Vererbung aufgrund von Faulheit zu nehmen ist unsinnig und kontraproduktiv. Nur weil man setSize statt frame.setSize schreiben will Vererbung zu nehmen ist falsch.
klar, um Vererbung kommt man nicht drumherum, ich frage mich dabei, ob ihr das dann auch wie im Beispiel PaintPanel wieder per Attribut lösen würdet?
denn das Überschreiben bedeutet ja nicht, dass sonstiger Initialisierungs-Code auch in die neue JPanel-Subklasse gehört,
wenn aber doch dann ist die Einheitlichkeit schon ein einigermaßen bedeutender Grund, z.B. in der Außensicht wie vorher angesprochen:
auf höherer Ebene steht
Java:
add(getPaintPanel()); // geht direkt weil PaintPanel von JPanel erbt für paintComponent
add(getCompPanel().getPanel()); // geht nicht direkt weil Vererbung vermieden wurde
? das wäre doch schrecklich
als Alternativen bleibt nur
- PaintPanel und CompPanel erben beide nicht von JPanel, umständliche Konstruktion für paintComponent, siehe vorheriges Posting
- oder beide erben von JPanel, ganz normaler Standard, eine Klasse die Panel heißt darf auch ruhig ein JPanel sein (!)
wie ist die Wahl, Mischen, nie die eigenen Klassen erben lassen (sondern höchstens JPanel-Attribut) oder immer erben?
bei welchen anderen Klassen steht diese Entscheidung noch an?
bei Collections lohnt allein schon nicht wegen theoretischer Wahl unterschiedlicher Implementierungen,
Thread ist bekannt,
Applet macht es eher leicht weil Methoden zu implementieren sind, strenggenommen gilt aber dasselbe wie bei JPanel,
der Umstand wird auch gerne für alles andere genutzt, inkonsequent,
hier ein Beispiel dann auch mal wieder mit erbenden JPanel, Learning Java - Chapter 7 : Java
von Socket/ ServerSocket würde niemand erben, da sind die Vorlagen/ der Gebrauch sicher richtiger,
viel mehr fällt mir kaum ein
stimme Andre zu. Vererbung aufgrund von Faulheit zu nehmen ist unsinnig und kontraproduktiv. Nur weil man setSize statt frame.setSize schreiben will Vererbung zu nehmen ist falsch.
Hmm, also ich hatte das zu Anfang so gelernt bzw. beigebracht bekommen. Und bei mir hat das eigentlich auch nichts mit Faulheit zu tun, sondern ich finde es eigentlich übersichtlicher, wenn mein Hauptframe in einer eigenen Klasse steht und diese Klasse dann auch ein JFrame sein kann (weil es ja auch einer ist). Warum nicht. Dachte ich jedenfalls bisher immer. In meinem Hauptframe passiert ja eigentlich auch nicht so richtig viel: Titel, Grösse, Position auf dem Bildschirm, Menü, Toolbar, Statusleiste und dann das MainPanel in den CENTER-Bereich. Ich brauche also auch nicht die Möglichkeit, evtl. noch von einer anderen Klasse erben zu müssen.
Bisher hatte ich eine Startklasse (mit der main-Methode drin), in welcher ein Objekt des Hauptframes erzeugt wurde (einfach nur mit new HauptFrame() ). Ihr meint also, es wäre besser, wenn ich dort in dieser Klasse das JFrame-Objekt erzeugen, konfigurieren und mit den Komponenten füllen würde? So richtig überzeugt bin ich immer noch nicht. Ich sehe immer noch keine richtigen Nachteile, und Vorteile, ausser jetzt wegen der Übersichtlichkeit.
wir hatten hier schonmal die Diskussion und da kam raus, dass das Hauptproblem bei Swing leider ist, dass keine korrekte Schnitstellen zur Verfuegung stehen.
Ich sag auch nicht, dass man jegliche componente immer per Komposition nehmen soll.
Vererbung ist jedoch wie der Hammer in der Hand, und alles sieht dann aus wie ein Nagel.
das Problem mit der Vererbung vor allem ist eben das veroeffentlichen aller Methoden der Oberklasse. hat man einen Panel der ganz toll was bestimmtes macht, ein bestimmtes layout verwendet, somit die komponents toll anordnet etc. Nutzt man nun Vererbung geht die eigentliche addComp Methode unter all den anderen adds unter und jeder Verwender kann ganz leicht die Anordung bzw den gedachten Sinn der Component aushebeln bzw falsch gebrauchen. Bei der Komposition hat man nicht das Problem, da man dort nur die methoden so anbieten, wie ein Verwender sie nutzen soll.
Das jedoch ist in der Swing welt aufgrund der fehlenden Schnittstellen nicht so einfach zu realisieren.
Ich persoenlich wuerde es immer so machen dass ich mit Komposition anfange und nur wenn es definitiv nicht weiter geht Vererbung als Moeglichkeit in Betracht ziehen
Abschließend hierzu noch einmal vielen Dank.
Meine Frage wurde dahingehend beantwortet, bzw. sehe ich sie als beantwortet an, dass das Erben von JFrame eigentlich nicht richtig ist, so lange man nicht die Funktionalität des Fensters verändern muss.
Trotzdem sieht man es immer wieder in Code-Beispielen und so wie einige berichtet haben, scheint es ja auch durchaus gelehrt worden zu sein/wird es noch.
Erstmal gibt's im statischen Kontext sowas wie einen Konstruktor gar nicht. Ein Konstruktor erzeugt ein Objekt. Und der nicht-statische Init-Block ist auch kein Konstruktor, denn ein Konstruktor wird nach wie vor aufgerufen. Der Init-Block wird im Zuge der Instanz-Initialisierung ausgeführt, vor dem Konstruktor. Mach doch mal ein Sysout in deinen "normalen Konstruktor" oben, und eines da rein was du als "anonymen" Konstruktor bezeichnest. Und dann erzeug mal eine Instanz.