From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001
From: Sven Eisenhauer
Date: Fri, 10 Nov 2023 15:11:48 +0100
Subject: add new repo
---
.../hjp5/html/k100055.html | 447 +++++++++++++++++++++
1 file changed, 447 insertions(+)
create mode 100644 Master/Reference Architectures and Patterns/hjp5/html/k100055.html
(limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100055.html')
diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100055.html b/Master/Reference Architectures and Patterns/hjp5/html/k100055.html
new file mode 100644
index 0000000..1043fa0
--- /dev/null
+++ b/Master/Reference Architectures and Patterns/hjp5/html/k100055.html
@@ -0,0 +1,447 @@
+
+
+
+Handbuch der Java-Programmierung, 5. Auflage
+
+
+
+
+
+
+
+
+| Titel
+ | Inhalt
+ | Suchen
+ | Index
+ | DOC
+ | Handbuch der Java-Programmierung, 5. Auflage
+ |
+| <<
+ | <
+ | >
+ | >>
+ | API
+ | Kapitel 8 - OOP II: Vererbung, Polymorphismus und statische Elemente
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+8.4.1 Abstrakte Klassen
+
+
+In Java ist es möglich, abstrakte Methoden zu definieren.
+Im Gegensatz zu den konkreten Methoden enthalten sie nur die
+Deklaration der Methode, nicht aber ihre Implementierung. Syntaktisch
+unterscheiden sich abstrakte Methoden dadurch, dass anstelle der geschweiften
+Klammern mit den auszuführenden Anweisungen lediglich ein Semikolon
+steht. Zusätzlich wird die Methode mit dem Attribut abstract
+versehen. Abstrakte Methoden können nicht aufgerufen werden,
+sie definieren nur eine Schnittstelle. Erst durch Überlagerung
+in einer abgeleiteten Klasse und Implementierung des fehlenden Methodenrumpfes
+wird eine abstrakte Klasse konkret und kann aufgerufen werden.
+
+
+
+
+
+
+
+
+8.4.2 Ein Beispiel für Polymorphismus
+
+
+Wir wollen uns ein Beispiel ansehen, um diese Ausführungen zu
+verdeutlichen. Zum Aufbau einer Mitarbeiterdatenbank soll zunächst
+eine Basisklasse definiert werden, die jene Eigenschaften implementiert,
+die auf alle Mitarbeiter zutreffen, wie beispielsweise persönliche
+Daten oder der Eintrittstermin in das Unternehmen. Gleichzeitig
+soll diese Klasse als Basis für spezialisierte Unterklassen verwendet
+werden, um die Besonderheiten spezieller Mitarbeitertypen, wie Arbeiter,
+Angestellte oder Manager, abzubilden. Da die Berechnung
+des monatlichen Gehalts zwar für jeden Mitarbeiter erforderlich,
+in ihrer konkreten Realisierung aber abhängig vom Typ des Mitarbeiters
+ist, soll eine abstrakte Methode monatsBrutto
+in der Basisklasse definiert und in den abgeleiteten Klassen konkretisiert
+werden.
+
+
+Das folgende Listing zeigt die Implementierung der Klassen Mitarbeiter,
+Arbeiter, Angestellter
+und Manager zur Realisierung
+der verschiedenen Mitarbeitertypen. Zusätzlich wird die Klasse
+Gehaltsberechnung definiert,
+um das Hauptprogramm zur Verfügung zu stellen, in dem die Gehaltsberechnung
+durchgeführt wird. Dazu wird ein Array ma
+mit konkreten Untertypen der Klasse Mitarbeiter
+gefüllt (hier nur angedeutet; die Daten könnten zum Beispiel
+aus einer Datenbank gelesen werden) und dann für alle Elemente
+das Monatsgehalt durch Aufruf von monatsBrutto
+ermittelt.
+
+
+
+
+
+
+
+
+
+
+001 /* Gehaltsberechnung.java */
+002
+003 import java.util.Date;
+004
+005 abstract class Mitarbeiter
+006 {
+007 int persnr;
+008 String name;
+009 Date eintritt;
+010
+011 public Mitarbeiter()
+012 {
+013 }
+014
+015 public abstract double monatsBrutto();
+016 }
+017
+018 class Arbeiter
+019 extends Mitarbeiter
+020 {
+021 double stundenlohn;
+022 double anzahlstunden;
+023 double ueberstundenzuschlag;
+024 double anzahlueberstunden;
+025 double schichtzulage;
+026
+027 public double monatsBrutto()
+028 {
+029 return stundenlohn*anzahlstunden+
+030 ueberstundenzuschlag*anzahlueberstunden+
+031 schichtzulage;
+032 }
+033 }
+034
+035 class Angestellter
+036 extends Mitarbeiter
+037 {
+038 double grundgehalt;
+039 double ortszuschlag;
+040 double zulage;
+041
+042 public double monatsBrutto()
+043 {
+044 return grundgehalt+
+045 ortszuschlag+
+046 zulage;
+047 }
+048 }
+049
+050 class Manager
+051 extends Mitarbeiter
+052 {
+053 double fixgehalt;
+054 double provision1;
+055 double provision2;
+056 double umsatz1;
+057 double umsatz2;
+058
+059 public double monatsBrutto()
+060 {
+061 return fixgehalt+
+062 umsatz1*provision1/100+
+063 umsatz2*provision2/100;
+064 }
+065 }
+066
+067 public class Gehaltsberechnung
+068 {
+069 private static final int ANZ_MA = 100;
+070 private static Mitarbeiter[] ma;
+071 private static double bruttosumme;
+072
+073 public static void main(String[] args)
+074 {
+075 ma = new Mitarbeiter[ANZ_MA];
+076
+077 //Mitarbeiter-Array füllen, z.B.
+078 //ma[0] = new Manager();
+079 //ma[1] = new Arbeiter();
+080 //ma[2] = new Angestellter();
+081 //...
+082
+083 //Bruttosumme berechnen
+084 bruttosumme = 0.0;
+085 for (int i=0; i<ma.length; ++i) {
+086 bruttosumme += ma[i].monatsBrutto();
+087 }
+088 System.out.println("Bruttosumme = "+bruttosumme);
+089 }
+090 }
+
+ |
+
+Gehaltsberechnung.java |
+
+
+
+Listing 8.11: Abstrakte Klassen und Methoden
+
+
+Unabhängig davon, ob in einem Array-Element ein Arbeiter, Angestellter
+oder Manager gespeichert wird, führt der Aufruf von monatsBrutto
+dank der dynamischen Methodensuche die zum Typ des konkreten Objekts
+passende Berechnung aus. Auch weitere Verfeinerungen der Klassenhierarchie
+durch Ableiten neuer Klassen erfordern keine Veränderung in der
+Routine zur Berechnung der monatlichen Bruttosumme.
+
+
+So könnte beispielsweise eine neue Klasse GFManager
+(ein Manager, der Mitglied der Geschäftsführung ist) aus
+Manager abgeleitet und problemlos in die Gehaltsberechnung integriert
+werden:
+
+
+
+
+
+
+
+
+001 public class GFManager
+002 extends Manager
+003 {
+004 double gfzulage;
+005
+006 public double monatsBrutto()
+007 {
+008 return super.monatsBrutto()+gfzulage;
+009 }
+010 }
+
+ |
+
+
+
+Listing 8.12: Einfügen einer neuen Mitarbeiterklasse in die Gehaltsberechnung
+
+
+
+
+
+
+8.4.3 Polymorphe Methodenaufrufe in Konstruktoren
+
+
+Eine besondere Gefahrenquelle liegt darin, polymorphe Methoden im
+Konstruktor einer Klasse aufzurufen. Der Grund liegt in der Initialisierungsreihenfolge
+von Membervariablen während der Konstruktion eines Objekts:
+
+- Zuerst werden die Konstruktoren der Vaterklassen aufgerufen und
+so deren Membervariablen initialisiert.
+
- Dann werden die Initialisierer und initialisierenden Zuweisungen
+der eigenen Klasse aufgerufen.
+
- Schließlich wird der Rumpf des eigenen Konstruktors ausgeführt.
+
+
+
+Wird nun im eigenen Konstruktor eine Methode aufgerufen, die in einer
+abgeleiteten Klasse überlagert wurde, sind die Membervariablen
+der abgeleiteten Klasse noch nicht initialisiert. Ihr Konstruktor
+wird ja erst später aufgerufen. Das folgende Beispiel illustriert
+dieses Problem:
+
+
+
+
+
+
+
+
+001 /* Listing0813.java */
+002
+003 class SingleValue
+004 {
+005 protected int value1;
+006
+007 public SingleValue(int value1)
+008 {
+009 this.value1 = value1;
+010 print();
+011 }
+012
+013 public void print()
+014 {
+015 System.out.println("value = " + value1);
+016 }
+017 }
+018
+019 class ValuePair
+020 extends SingleValue
+021 {
+022 protected int value2;
+023
+024 public ValuePair(int value1, int value2)
+025 {
+026 super(value1);
+027 this.value2 = value2;
+028 }
+029
+030 public void print()
+031 {
+032 System.out.println(
+033 "value = (" + value1 + "," + value2 + ")"
+034 );
+035 }
+036 }
+037
+038 public class Listing0813
+039 {
+040 public static void main(String[] args)
+041 {
+042 new ValuePair(10,20);
+043 }
+044 }
+
+ |
+
+Listing0813.java |
+
+
+
+Listing 8.13: Polymorphe Methodenaufrufe im Konstruktor
+
+
+Die Ausgabe des Programms ist nicht »value = 10«, sondern
+»value = (10,0)«. Bei der Konstruktion des ValuePair-Objekts
+wird zunächst der Konstruktor der Basisklasse SingleValue
+aufgerufen und initialisiert seine Membervariable value1.
+Der anschließende Aufruf von print
+wird polymorph ausgeführt, denn das zu instanzierende Objekt
+ist vom Typ ValuePair. Da zu
+diesem Zeitpunkt der Member value2
+aber noch nicht initialisiert ist (das würde erst passieren,
+wenn der Konstruktor von SingleValue
+komplett abgearbeitet wäre), wird an seiner Stelle 0 ausgegeben
+(beim Anlegen eines neuen Objekts wird der belegte Speicher mit Nullen
+gefüllt). Das kann zu schwer auffindbaren Fehlern führen.
+Aufrufe von Methoden, die möglicherweise überlagert werden,
+sollten daher im Konstruktor vermieden werden.
+
+
+
+
+
--
cgit v1.2.3