1 Abstrakte Klassen, finale Klassen und Interfaces
Transcription
1 Abstrakte Klassen, finale Klassen und Interfaces
1 Abstrakte Klassen, finale Klassen und Interfaces • Eine abstrakte Objekt-Methode ist eine Methode, für die keine Implementierung bereit gestellt wird. • Eine Klasse, die abstrakte Objekt-Methoden enthält, heißt ebenfalls abstrakt. • Eine abstrakte Klasse kann nicht instanziiert werden. • Mit abstrakten Klassen können wir Unterklassen mit verschiedenen Implementierungen der gleichen Objekt-Methoden zusammenfassen. 1 Beispiel: Implementierung einer Mitarbeiterdatenbank abstract class Mitarbeiter { private int persnr; String name; Date eintritt; public Mitarbeiter() {} public int personalNummer(){return persnr}; public abstract double monatsBrutto(); } 2 • Die Unterklassen von Mitarbeiter repräsentieren die konkreten Mitarbeitertypen, die die Firma hat. • Allen Unterklassen gemeinsam ist eine Objekt-Methode monatsBrutto() – immer mit einer anderen Implementierung • Die statischen Variablen der Oberklasse stehen sämtlichen Unterklassen zur Verfügung. 3 • Eine abstrakte Objekt-Methode wird durch das Schlüsselwort abstract gekennzeichnet. • Eine Klasse, die eine abstrakte Methode enthält, muss selbst ebenfalls als abstract gekennzeichnet sein. • Für die abstrakte Methode muss der vollständige Kopf angegeben werden – inklusive den Parameter-Typen und den (möglicherweise) geworfenen Exceptions. • Die konkrete Default-Implementierung für int personalNummer() kann von anderen Klassen überschrieben werden. • Die Methode monatsBrutto() soll den Monatslohn eines Mitarbeitertyps berechnen zurückliefern. 4 Beispiel für unterschiedliche Mitarbeitertypen: class Arbeiter extends Mitarbeiter { double stundenlohn; double anzahlstunden; double ueberstundenzuschlag; double anzahlueberstunden; double schichtzulage; public double monatsBrutto() { return stundenlohn*anzahlstunden+ ueberstundenzuschlag*anzahlueberstunden+ schichtzulage; } } 5 class Angestellter extends Mitarbeiter { double grundgehalt; double ortszuschlag; double zulage; public double monatsBrutto() { return grundgehalt+ ortszuschlag+ zulage; } } 6 class Manager extends Mitarbeiter { double fixgehalt; double provision1; double provision2; double umsatz1; double umsatz2; public double monatsBrutto() { return fixgehalt+ umsatz1*provision1/100+ umsatz2*provision2/100; } } 7 public class Example{ private static final int ANZ_MA = 100; private static Mitarbeiter ma[]; private static double bruttosumme; public static void main(String args[]) { ma = new Mitarbeiter[ANZ_MA]; //Mitarbeiter-Array füllen, z.B. //ma[0] = new Manager(); //ma[1] = new Arbeiter(); //ma[2] = new Angestellter(); //... 8 //Bruttosumme berechnen bruttosumme = 0.0; for (int i=0; i<ma.length; ++i) { bruttosumme += ma[i].monatsBrutto(); } //Welche konkrete Methode jeweils aufgerufen wird, //hängt von der konkreten Klasse des jeweiligen Objekts //ab, d.h. entscheidet sich erst zur Laufzeit //Dynamische Binding oder Dynamic Method Lookup write("Bruttosumme = "+bruttosumme); } } 9 Der final-Modifier • Wird eine Klasse als final deklariert, bedeutet das, dass von der Klasse keine Klasse abgeleitet werden kann. • Wird eine Variable als final deklariert, bedeutet das, dass die Variable konstant ist. • Wird eine Methode als final deklariert, bedeutet das, dass die Methode in Unterklassen nicht überschrieben werden kann. Der Zweck von final Deklarationen: • Sicherheit: Niemand soll in der Lage sein, Subklassen und neue oder andere Instanzen zu erstellen. • Effizienz: Es können Compileroptimierungen durchgeführt werden, da sich Instanzen nur in einer Klasse (nicht in Subklassen) befinden. 10 Beispiel public void } public void } final class Ober { sicher() { } class Unter extends Ober { // Compilerfehler! sicher() { } class Ober { final void sicher() { } } class Unter extends Ober { void sicher() { } // Compilerfehler! } 11 Leider (zum Glück?) lässt sich nicht die ganze Welt hierarchisch organisieren 12 Beispiel: Comparable AddSubMulDiv Rational Complex AddSubMulDiv = Objekte mit Operationen add(), sub(), mul(), und div() Comparable = Objekte, die eine compareTo()-Operation besitzen. 13 • Mehrere direkte Oberklassen einer Klasse führen zu konzeptuellen Problemen: • Auf welche Klasse bezieht sich super ? • Welche Objekt-Methode meth() ist gemeint, wenn wenn mehrere Oberklassen meth() implementieren ? meth() A meth() B C 14 • Kein Problem entsteht, wenn die Objekt-Methode meth() in allen Oberklassen abstrakt ist • oder zumindest nur in maximal einer Oberklasse eine Implementierung besitzt Ganz allgemein ist das Problem also, dass Klassen nur eine Basisklasse in einer Vererbungshierarchie haben dürfen. Um dieses Problem zu umgehen, kann man in Schnittstellendefinitionen die zu implementierenden Methoden und Datenelemente bestimmen. 15 • Kein Problem entsteht, wenn die Objekt-Methode meth() in allen Oberklassen abstrakt ist • oder zumindest nur in maximal einer Oberklasse eine Implementierung besitzt Ganz allgemein ist das Problem also, dass Klassen nur eine Basisklasse in einer Vererbungshierarchie haben dürfen. Um dieses Problem zu umgehen, kann man in Schnittstellendefinitionen die zu implementierenden Methoden und Datenelemente bestimmen. 16 Eine Schnittstelle (Interface) kann aufgefasst werden als eine abstrakte Klasse, wobei: • alle Objekt-Methoden abstrakt sind, also lediglich Methodendeklarationen (die Signaturen: Methodenname, Namen, Anzahl, Reihenfolge und Typen der Parameter, Typ des Rückgabewertes) ohne einen Anweisungsrumpf enthalten; • es keine Klassen-Methoden gibt; • alle Variablen Konstanten sind; • kein Konstruktor definiert werden darf. 17 Was bringen Interfaces? • Zuerst einmal keine Einsparungen bei der Programmierung! • Über Schnittstellen lässt sich allerdings eine Sicht auf ein Objekt beschreiben. Jede Schnittstelle definiert eine Sicht (ein Rolle), und implementiert eine Klasse mehrere Schnittstellen, dann können die Instanzen in verschiedenen Rollen auftreten. • Schnittstellen repräsentieren eine Garantie bezüglich der in einer Klasse vorhandenen Methoden. Sie geben an, dass alle Objekte, die diese Schnittstelle besitzen, gleich behandelt werden können. • Schnittstellen werden verwendet, um Kompatibilitäten zwischen Klassen zu definieren, die nicht voneinander erben. 18 Beispiel: public interface Comparable { int compareTo(Object x); } • Object ist die gemeinsame Oberklasse aller Klassen. • Methoden in Interfaces sind automatisch Objekt-Methoden und public. • Evt. vorkommende Konstanten sind automatisch public static. 19 Beispiel (Forts.): public class Rational extends AddSubMulDiv implements Comparable { private int zaehler, nenner; public int compareTo(Object cmp) { Rational fraction = (Rational) cmp; long left = zaehler * fraction.nenner; long right = nenner * fraction.zaehler; if (left == right) return 0; else if (left < right) return -1; else return 1; } // end of compareTo ... } // end of class Rational 20 • class A extends B implements B1, B2,...,Bk {...} gibt an, dass die Klasse A als Oberklasse B hat und zusätzlich die Interfaces B1, B2,...,Bk unterstützt, d.h. passende Objekt-Methoden zur Verfügung stellt. • Java gestattet maximal eine Oberklasse, aber beliebig viele implementierte Interfaces. • Die Konstanten des Interface können in implementierenden Klassen direkt benutzt werden. • Interfaces können als Typen für formale Parameter, Variablen oder Rückgabewerte benutzt werden. • Darin abgelegte Objekte sind dann stets aus einer implementierenden Klasse. • Expliziter Cast in eine solche Klasse ist möglich 21 • Interfaces können andere Interfaces erweitern oder gar mehrere andere Interfaces zusammenfassen. • Erweiternde Interfaces können Konstanten umdefinieren... • Kommt eine Konstante gleichen Namens const in verschiedenen implementierten Interfaces A und B vor, kann man sie durch A.const und B.const unterscheiden Beispiel (Forts.): public interface Countable extends Comparable, Cloneable { Countable next(); Countable prev(); int number(); } 22 • Das Interface Countable umfasst die (beiden vordefinierten) Interfaces Comparable und Cloneable. • Das vordefinierte Interface Cloneable verlangt eine Objekt-Methode public Object clone() die eine Kopie des Objekts anlegt. • Eine Klasse, die Countable implementiert, muss über die Objekt-Methoden compareTo(), clone(), next(), prev() und number() verfügen. 23 Übersicht: Object Interfaces Cloneable Countable Comparable Rational AddSubMulDiv Complex Klassen-Hierarchie 24