Warum man nicht von JFrame/JDialog erben sollte: Unterschied zwischen den Versionen
(Die Seite wurde neu angelegt: „== Warum man nicht von JFrame/JDialog erben sollte == Dieser Beitrag wurde von '''Firephoenix''' erstellt Es ist doch verwunderlich wie oft man so etwas hier s…“) |
K |
||
(11 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
− | |||
− | |||
− | |||
Dieser Beitrag wurde von '''Firephoenix''' erstellt | Dieser Beitrag wurde von '''Firephoenix''' erstellt | ||
Es ist doch verwunderlich wie oft man so etwas hier sieht: | Es ist doch verwunderlich wie oft man so etwas hier sieht: | ||
− | < | + | <syntaxhighlight lang="java">public class Gui extends JFrame{ |
public Gui(){ | public Gui(){ | ||
super("Toller titel"); | super("Toller titel"); | ||
setDefaultCloseOperation(EXIT_ON_CLOSE); | setDefaultCloseOperation(EXIT_ON_CLOSE); | ||
− | getContentPane().add(new JButton(" | + | getContentPane().add(new JButton("Out Of Order")); |
pack(); | pack(); | ||
setVisible(true); | setVisible(true); | ||
} | } | ||
− | }</ | + | }</syntaxhighlight> |
Sieht irgendwie bekannt aus, oder? | Sieht irgendwie bekannt aus, oder? | ||
− | Und: Normalerweise würgt man die VM auch nicht mit < | + | Und: Normalerweise würgt man die VM auch nicht mit <syntaxhighlight lang="java">System.exit(0);</syntaxhighlight> respektive <syntaxhighlight lang="java">frame.setDefaultCloseOperation(EXIT_ON_CLOSE);</syntaxhighlight> ab, sondern ruft <syntaxhighlight lang="java">dispose()</syntaxhighlight> auf. |
Tatsächlich ist der Code genauso furchtbar wie das hier: | Tatsächlich ist der Code genauso furchtbar wie das hier: | ||
− | < | + | <syntaxhighlight lang="java">public class Buchregal extends ArrayList<String>{ |
public Buchregal(){ | public Buchregal(){ | ||
Zeile 29: | Zeile 26: | ||
add("Handbuch der Java Programmierung"); | add("Handbuch der Java Programmierung"); | ||
} | } | ||
− | }</ | + | }</syntaxhighlight> |
Und mal ehrlich, wer würde auf die Idee kommen, so etwas anzustellen? | Und mal ehrlich, wer würde auf die Idee kommen, so etwas anzustellen? | ||
Zeile 36: | Zeile 33: | ||
(zugegeben es ist kein schönes Buchregal das nur die Titel kennt) | (zugegeben es ist kein schönes Buchregal das nur die Titel kennt) | ||
− | < | + | <syntaxhighlight lang="java">public class Buchregal{ |
private ArrayList<String> buchtitel; | private ArrayList<String> buchtitel; | ||
Zeile 46: | Zeile 43: | ||
buchtitel.add("Handbuch der Java Programmierung"); | buchtitel.add("Handbuch der Java Programmierung"); | ||
} | } | ||
− | }</ | + | }</syntaxhighlight> |
Und genau so kann man auch mit der GUI-Klasse verfahren: | Und genau so kann man auch mit der GUI-Klasse verfahren: | ||
− | < | + | <syntaxhighlight lang="java">public class Gui{ |
private JFrame frame; | private JFrame frame; | ||
Zeile 57: | Zeile 54: | ||
frame = new JFrame("Toller titel"); | frame = new JFrame("Toller titel"); | ||
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); | frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); | ||
− | frame | + | frame.add(new JButton("Out Of Order")); |
frame.pack(); | frame.pack(); | ||
frame.setVisible(true); | frame.setVisible(true); | ||
} | } | ||
− | }</ | + | }</syntaxhighlight> |
Nur was hat man jetzt eigentlich gemacht? | Nur was hat man jetzt eigentlich gemacht? | ||
Zeile 72: | Zeile 69: | ||
'''Verwenden != Erweitern''' | '''Verwenden != Erweitern''' | ||
− | + | ||
− | + | ''Irgendwo im Forum hat das L-ectron-X mal recht treffend formuliert:'' | |
− | + | Wenn wir von einer Klasse erben, sprechen wir auch davon, sie zu spezialisieren. | |
− | Genauso, wie der Vater persönliche Eigenschaften an den Sohn vererbt, bekommt in der OOP eine erbende Klasse die Eigenschaften (Methoden und öffentliche Instanzvariablen) der Basisklasse (auch Superklasse) eingepflanzt. Die erbende Klasse muss aber für eine sinnvolle Anwendung der Vererbung weitere Eigenschaften erhalten, und/oder bestehende Eigenschaften spezialisieren. | + | Genauso, wie der Vater persönliche Eigenschaften an den Sohn vererbt, bekommt in der OOP eine erbende Klasse die Eigenschaften (Methoden und öffentliche Instanzvariablen) der Basisklasse (auch Superklasse) eingepflanzt. Die erbende Klasse muss aber für eine sinnvolle Anwendung der Vererbung weitere Eigenschaften erhalten, und/oder bestehende Eigenschaften spezialisieren. |
− | Genauso wie der Sohn vom Vater die Fähigkeit erbte, besonders schnell die 60m zu laufen, kann der Sohn nun aber auch noch die 100m besonders schnell laufen. Eine Fähigkeit, zu der der Vater nicht im Stande ist. | + | Genauso wie der Sohn vom Vater die Fähigkeit erbte, besonders schnell die 60m zu laufen, kann der Sohn nun aber auch noch die 100m besonders schnell laufen. Eine Fähigkeit, zu der der Vater nicht im Stande ist. |
− | + | ||
Wie es im Englischen schön heißt: composition over inheritance. | Wie es im Englischen schön heißt: composition over inheritance. | ||
Zeile 90: | Zeile 87: | ||
Ein Fall wo es tatsächlich Sinn macht von einer Grafikkomponente zu erben wäre dieser hier: | Ein Fall wo es tatsächlich Sinn macht von einer Grafikkomponente zu erben wäre dieser hier: | ||
− | < | + | <syntaxhighlight lang="java">public class PaintingPanel extends JPanel{ |
@Override | @Override | ||
− | + | protected void paintComponent(Graphics g){ | |
super.paintComponent(g); | super.paintComponent(g); | ||
g.drawLine(3, 3, 6, 6); | g.drawLine(3, 3, 6, 6); | ||
} | } | ||
− | } </ | + | } </syntaxhighlight> |
Hier haben wir das JPanel tatsächlich erweitert, nämlich um eine hässliche kleine Linie die darauf gezeichnet wird | Hier haben wir das JPanel tatsächlich erweitert, nämlich um eine hässliche kleine Linie die darauf gezeichnet wird | ||
Zeile 112: | Zeile 109: | ||
composition over inheritance | composition over inheritance | ||
+ | |||
+ | {{Fragen stellen}} | ||
+ | |||
+ | --[[Benutzer:Firephoenix|Firephoenix]] 19:18, 28. Aug 2013 (CET) | ||
+ | |||
+ | [[Kategorie:Swing]] | ||
+ | [[Kategorie:Java Grundlagen]] |
Aktuelle Version vom 8. April 2018, 11:22 Uhr
Dieser Beitrag wurde von Firephoenix erstellt
Es ist doch verwunderlich wie oft man so etwas hier sieht:
public class Gui extends JFrame{
public Gui(){
super("Toller titel");
setDefaultCloseOperation(EXIT_ON_CLOSE);
getContentPane().add(new JButton("Out Of Order"));
pack();
setVisible(true);
}
}
Sieht irgendwie bekannt aus, oder?
Und: Normalerweise würgt man die VM auch nicht mit
System.exit(0);
respektive
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
ab, sondern ruft
dispose()
auf.
Tatsächlich ist der Code genauso furchtbar wie das hier:
public class Buchregal extends ArrayList<String>{
public Buchregal(){
add("Spiele programmieren mit Java");
add("Spring im Einsatz");
add("Handbuch der Java Programmierung");
}
}
Und mal ehrlich, wer würde auf die Idee kommen, so etwas anzustellen?
Da schreibt man ein Buchregal, das 3 Buchtitel enthält, doch lieber so oder? (zugegeben es ist kein schönes Buchregal das nur die Titel kennt)
public class Buchregal{
private ArrayList<String> buchtitel;
public Buchregal(){
buchtitel = new ArrayList<String>();
buchtitel.add("Spiele programmieren mit Java");
buchtitel.add("Spring im Einsatz");
buchtitel.add("Handbuch der Java Programmierung");
}
}
Und genau so kann man auch mit der GUI-Klasse verfahren:
public class Gui{
private JFrame frame;
public Gui(){
frame = new JFrame("Toller titel");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(new JButton("Out Of Order"));
frame.pack();
frame.setVisible(true);
}
}
Nur was hat man jetzt eigentlich gemacht?
In den ersten 2 Beispielen haben wir Vererbung benutzt, um eine Klasse zu verwenden. Das Stichwort hier ist "verwenden" und nicht "erweitern"! Wir haben lediglich bestehende Funktionen der Klasse JFrame verwendet, aber keine neue Funktionalität hinzugefügt. Solange wir das nicht machen, besteht kein Grund von einer Klasse zu erben!
Verwenden != Erweitern
Irgendwo im Forum hat das L-ectron-X mal recht treffend formuliert:
Wenn wir von einer Klasse erben, sprechen wir auch davon, sie zu spezialisieren. Genauso, wie der Vater persönliche Eigenschaften an den Sohn vererbt, bekommt in der OOP eine erbende Klasse die Eigenschaften (Methoden und öffentliche Instanzvariablen) der Basisklasse (auch Superklasse) eingepflanzt. Die erbende Klasse muss aber für eine sinnvolle Anwendung der Vererbung weitere Eigenschaften erhalten, und/oder bestehende Eigenschaften spezialisieren. Genauso wie der Sohn vom Vater die Fähigkeit erbte, besonders schnell die 60m zu laufen, kann der Sohn nun aber auch noch die 100m besonders schnell laufen. Eine Fähigkeit, zu der der Vater nicht im Stande ist.
Wie es im Englischen schön heißt: composition over inheritance.
Wir benutzen daher möglichst Felder anstatt Vererbung.
Felder können jederzeit ausgetauscht werden, unser Bücherregal könnte zur Programmlaufzeit die ArrayList durch eine LinkedList ersetzen, (oder wenn der typ des Feldes nur Collection <String> wäre), sogar auf ein HashSet umsteigen. Benutzen wir dagegen Vererbung sind wir für alle Ewigkeit an die ArrayList gebunden und können zur Laufzeit nicht mehr davon weg. Außerdem wird die Vererbung Teil der API unserer Software, ein anderer Programmierer wird unsere Komponente z.B. auch wie eine ArrayList verwenden, auch hier haben wir keine Möglichkeit etwas zu Ändern ohne anderen Code zu gefährden. Halten wir dagegen solche Implementierungsdetails in privaten Feldern versteckt können wir zu jeder Zeit daran herumspielen, ohne das jemand etwas davon mitbekommen wird.
Ein Fall wo es tatsächlich Sinn macht von einer Grafikkomponente zu erben wäre dieser hier:
public class PaintingPanel extends JPanel{
@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
g.drawLine(3, 3, 6, 6);
}
}
Hier haben wir das JPanel tatsächlich erweitert, nämlich um eine hässliche kleine Linie die darauf gezeichnet wird
Zu bemerken ist hier das @Override und der super-Aufruf. Es ist kein guter Stil, Methoden komplett zu überschreiben (z.B. würde das hier zu Zeichenfehlern im eigentlichen Panel führen), daher rufen wir zuerst die Methode der Superklasse auf. Weiterhin zeigt uns das @Override an, dass wir eine Methode der Superklasse überschrieben haben (und der Compiler meckert uns an wenn, wir sie falsch geschrieben haben -> gängige Fehlerquelle vermieden).
Generell also:
Wenn wir eine Klasse verwenden wollen, legen wir ein Feld mit dem Typ der Klasse an und verwenden das Feld.
Wenn wir eine bestehende Klasse um neue Funktionalität erweitern wollen, dann erben wir von der Klasse.
composition over inheritance
Fragen
Das Thema wurde nicht ausreichend behandelt? Du hast Fragen dazu und brauchst weitere Informationen? Lass Dir von uns helfen!
- Besuche uns im Byte-Welt-Forum
- Besuche unseren Chat
Wir helfen dir gerne!
Dir hat dieser Artikel gefallen? Oder Du hast Fehler entdeckt und möchtest zur Berichtigung beitragen? Prima! Schreibe einen Kommentar!
Du musst angemeldet sein, um einen Kommentar abzugeben.
--Firephoenix 19:18, 28. Aug 2013 (CET)