Kurs OPR Objektorientierte Programmierung Lektion: 006-Abstrakte Klassen, Interfaces etc. Zürcher Hochschule für Angewandte Wissenschaften Mitglied der Fachhochschule Zürich Version 1.4 Inhaltsverzeichnis 1 2 Abstrakte Klassen und Interfaces 3 1.1 Ziele 3 1.2 Abstrakte Klassen 3 1.3 Interface (Schnittstelle) 5 1.4 Mehrfachvererbung und Interfaces 8 1.5 Interfaces vs. abstrakte Klassen 8 1.6 Adapterklassen 9 1.7 Professionelles Programmieren 10 Programmpakete 11 2.1 Ziele 11 2.2 Packages 11 2.3 Importieren von Klassen und Packages 12 2.4 Sichtbarkeitsregeln für Packages 13 2.5 Professionelles Programmieren 15 Abstrakte Klassen, Interfaces etc.doc © 2010 InIT/ZHAW 2 1 Abstrakte Klassen und Interfaces 1.1 • • • • 1.2 • Ziele Sie können die Begriffe abstrakte Klasse, Methode und Interface erklären. Sie können mit abstrakten Klassen und Interfaces umgehen. Sie können an Beispielen erklären, wie und wozu abstrakte Klassen und Interfaces verwendet werden. Sie können eigene abstrakte Klassen und Interfaces schreiben. Abstrakte Klassen Problemstellung − Beispiel: − Wir möchten ein Package schreiben, das Klassen für verschiedene Figuren enthält (Rechteck, Ellipse, Dreieck). − Die Figuren sollen alle die gleiche Funktionalität haben − Mögliche Klassenhierarchie des Package: Figur int xPos, yPos int breite, hoehe setSize(int b, int h) setPosition(int x, int y) anzeigen(Graphics g) float getFlaeche() Rechteck Kreis int radius anzeigen(Graphics g) float getFlaeche() anzeigen(Graphics g) float getFlaeche() Abbildung 1: Mögliche Klasserhierarchie eines Package für Figuren − Methoden, die alle Subklassen haben müssen, werden in der Superklasse deklariert. (Dank Polymorphismus wird jeweils die richtige Methode ausgewählt) Abstrakte Klassen, Interfaces etc.doc © 2010 InIT/ZHAW 3 − − − − Einige Methode können auch in der Superklasse implementiert werden. Beispiel: setSize(int b, int h), setPosition(int x, int y) Andere Methoden können hingegen nicht sinnvoll implementiert werden Beispiel: anzeigen(Graphics g), float getFlaeche() Problem: Wie stellt man sicher, dass auch zukünftige Subklassen von Figur, die gemeinsamen Methoden implementieren? Lösung: Æ abstrakte Methoden und Klassen: Die Methoden anzeigen(Graphics g) und float getFlaeche() werden als abstract deklariert: public abstract void anzeigen(Graphics g); public abstract float getFlaeche(); • Abstrakte Methoden − haben nur einen Methodenkopf (Signatur), keinen Methodenkörper − haben einen Strichpunkt (;) nach der Signatur − haben den Modifikator abstract im Methodenkopf − Folge für die Klasse Figur: Sobald eine Methode der Klasse Figur abstract ist, muss auch die Klasse selbst als abstract deklariert sein: public abstract class Figur{ public abstract void anzeigen(Grapics g); public abstract float getFlaeche(); } • Abstrakte Klasse − Eine abstrakte Klasse hat mindestens eine abstrakte Methode und/oder ist als abstract deklariert. − Sie kann nicht instanziert werden. − Subklassen von abstrakten Klassen müssen die abstrakten Methoden implementieren. − Falls sie das nicht tun, müssen sie ebenfalls als abstract deklariert sein. − Beispiel von Abbildung 1: Die Klasse Rechteck wird von Klasse Figur abgeleitet und implementiert die abstrakten Methoden: class Rechteck extends Figur{ public void anzeigen(Graphics g){ g.drawRect(xPos, yPos, breite, hoehe); } public float getFlaeche(){ return (float) breite*hoehe; } } Abstrakte Klassen, Interfaces etc.doc © 2010 InIT/ZHAW 4 • Aufgabe: Leiten Sie die Klasse Kreis von der abstrakten Klasse Figur ab. • Lösung: • Vorteile durch die Verwendung von abstrakten Klassen: − Ein bestimmtes Klassendesign kann erzwungen werden. − Sie erlaubt die Klassenbeschreibung in höheren Abstaktionsebenen: Von der Klasse Figur von oben können keine Objekte erzeugt werden. Sie fasst aber alle Objekte mit bestimmten Eigenschaften unter einem neuen Namen zusammen. − Analogie in der Biologie: Ein Säugetier existiert selbst nicht, sondern ist ein Sammelbegriff (Abstraktion) von real existierenden Tieren. − Alles in allem: Æ Abstrakte Klassen erleichtern die Planung und den Aufbau von Klassenhierarchien 1.3 • • Interface (Schnittstelle) Ein Interface definiert eine Schnittstelle zwischen Klassen (siehe Abbildung 2). Ein Interface ist eine Klasse, die nur aus Methodenköpfen besteht. Beispiel: public interface Ballon { public void changeSize(int newDiameter); public void move(int newX, int newY); public void display(Graphics g); } Abstrakte Klassen, Interfaces etc.doc © 2010 InIT/ZHAW 5 Klasse 1: Klasse A: verwendet Interface P implementiert Interface P Interface P + _ Klasse 2: implementiert Interface P Klasse B: . . . verwendet Interface P Klasse 4: implementiert Interface P Abbildung 2: Interface • • Merkmale eines Interfaces − Interfaces definieren wie Klassen einen neuen Datentyp. − Es können somit Variablen dieses Datentyps deklariert werden, z.B.: Ballon ball; − Interfaces können wie Klassen an Sub-Interfaces weitervererbt werden. − Ein Interface ist immer abstract (abstract kann auch weggelassen werden). − Es können deshalb keine Objekte aus einem Interface erzeugt werden. − Ein Interface beschreibt nur die Schnittstelle (Klasse, Methoden, Parameter) einer Klassen, nicht deren Implementierung. − Alle Methoden eines Interfaces sind public und abstract, auch wenn sie nicht explizit so deklariert sind. − Methoden dürfen nicht static sein. − Hingegen sind alle Variablen eines Interfaces static final (d.h. Konstanten) sein, auch wenn sie nicht explizit so deklariert sind. − Interfaces können compiliert, aber nicht laufen gelassen werden. Æ Das Compilieren erlaubt Typenprüfung bei der Verwendung eines Interfaces. − Das compiliertes Interface wird ebenfalls als Class-Datei, InterfaceName.class, gespeichert. Implementieren von Interfaces: − Ein Interface wird durch eine Klasse implementiert, die alle Methoden des Interfaces implementiert. − Deklaration einer Klasse, die ein Interface implementiert: class MeineKlasse implements Interfacename {...} − − − Die Klasse muss alle Methoden des Interfaces Interfacename implementieren. Dies wird vom Compiler überprüft. Interfaces können wie Klassen andere Interfaces durch extends erweitern. Klassen, die ein Sub-Interface implementieren, müssen auch alle Methoden der Super-Interfaces Abstrakte Klassen, Interfaces etc.doc © 2010 InIT/ZHAW 6 − implementieren. Eine Klasse kann gleichzeitig mehrere Interfaces implementieren: class MeinKlasse implements Interface1, Interface2,... {...} • • Interfaces dienen zur Beschreibung von: − Klassen, die bestimmte Methoden zur Verfügung stellen. − ganzen Vererbungsstrukturen Interfaces können nicht verwendet werden für − Beschreibung der Implementation der einzelnen Methoden − Verwendung von anderen Klassen (hat-ein-Relation. Grund: Nur Konstanten in Interfaces erlaubt) • Beispiel für den Einsatz eines Interface: Methode zeichneLinksbuendig − − − Wir möchten eine Methode schreiben, die eine Anzahl beliebiger graphischer Objekte linksbündig darstellen kann. Die Objekte müssen die zwei Methoden setPosition und anzeigen zur Verfügung stellen. Dazu definieren wir folgendes Interface: import java.awt.*; public interface Darstellbar{ public void setPosition(int x, int y); public void anzeigen(Graphics g); } − Die Methode zeichneLinksbuendig sieht dann wie folgt aus: public void zeichneLinksbuendig(Graphics g, Darstellbar[] figuren, int xPos, int abstand){ for (int i=0; i<figuren.length; i++){ figuren[i].setPosition(xPos,i*abstand); figuren[i].anzeigen(g); } } − − − Beachten Sie: − zeichneLinksbuendig besitzt einen Array-Parameter vom Typ Darstellbar. Die Methode kann beliebige Objekte, die Darstellbar implementieren, darstellen. Aufgabe: − Schreiben Sie eine Klasse Rechteck, die das Interface Darstellbar implementiert. − Wie könnte man erreichen, dass alle Subklassen der Klasse Figur das DarstellbarInterface implementieren? Abstrakte Klassen, Interfaces etc.doc © 2010 InIT/ZHAW 7 − 1.4 • • • − − Lösung: Mehrfachvererbung und Interfaces Java erlaubt nur einfache Vererbung Mehrfachvererbung ist aber nachbildbar mit Interfaces, da eine Klasse mehrere Interfaces implementieren kann. Beispiel: − Das Applet MeinSpiel ist abgeleitet von der Klasse Applet (Vererbung) − Zusätzlich soll es die Interfaces ActionListener und MouseListener implementieren: public class MeinSpiel extends Applet implements ActionListener, MouseListener{ ... } − 1.5 • Darstellung in UML siehe Abbildung 3. Interfaces vs. abstrakte Klassen Unterschied zwischen abstakten Klassen und Interfaces: − Abstrakte Klassen können Methoden-Implementationen enthalten, Interfaces nicht. Abstrakte Klassen, Interfaces etc.doc © 2010 InIT/ZHAW 8 − − − Eine Klasse kann mehrere Interfaces implementieren, aber nur eine Klasse erweitern. Interfaces werden nur beim Compilieren gebraucht. Methoden abstrakter Klassen werden dagegen zur Laufzeit zum Programm gelinkt. Objekt Applet MouseListener MeinSpiel ActionListener Abbildung 3: Implementation von Interfaces in UML 1.6 • • Adapterklassen In Java sind sogenannte Adapterklassen für jedes EventListener-Interface vordefiniert: − Adapterklassen sind abstrakte Klassen, die das entsprechende Interface implementieren. − Vorteil: − Falls man nur eine Methode braucht, erweitert man einfacher die Adapterklasse, anstatt das ganze Interface zu implementieren. Beispiel: MouseListener − − − Interface schreibt schreibt vor, dass die folgenden 5 Methoden implementiert werden müssen: − mouseClicked(MouseEvent e) // Maustaste geclickt − mousePressed(MouseEvent e) // Maustaste gedrückt − mouseReleased(MouseEvent e) // Maustaste losgelassen − mouseEntered(MouseEvent e) // Cursor in Komponente // eingetreten − mouseExited(MouseEvent e) // Cursor hat Komponent // verlassen Falls man z.B. nur mouseClicked braucht, müssen die anderen trotzdem geschrieben werden. Alternative: − Verwendung (d.h. Erweiterung) der Klasse MouseAdapter: − Vorteil: Es muss nur die Methode mouseClicked überschrieben werden: public class MeineKlasse extends MouseAdapter{ public void mousClicked(MouseEvent e){...} } Abstrakte Klassen, Interfaces etc.doc © 2010 InIT/ZHAW 9 − 1.7 • • • Zu jedem Listener mit dem Namen XXXListener gibt es eine entsprechende Adapterklasse mit dem Namen XXXAdapter. Professionelles Programmieren Interfaces und alle Bestandteile davon gut dokumentieren − aus Sicht des Anwenders, nicht des Implementierers. Für Interfaces gelten die gleichen Regeln für die Namensgebung wie bei Klassennamen. Verwenden Sie Interfaces, um Klassen und Subsysteme zu entkoppeln. Abstrakte Klassen, Interfaces etc.doc © 2010 InIT/ZHAW 10 2 Programmpakete 2.1 • • 2.2 • • • • Ziele Sie können Klassen aus gegebenen Packages importieren. Sie können eigene Packages deklarieren. Packages Normalerweise befindet sich jede Java-Klasse in einem eigenen File mit dem gleichem Filenamen wie die Klasse. Falls zwei Klassen denselben Namen haben, so sind sie nicht mehr eindeutig identifizierbar. Abhilfe: Der gesamte Namensraum wird durch sogenannte Packages aufgeteilt. Packages − Fasst eine Gruppe von Klassen (und eventuell Subpackages) zusammen unter einem (möglichst eindeutigen) Namen − Beispiele: − java.applet : Alle Klassen im Zusammenhang mit Applets − java.awt : Die Klassen des Abstract-Windowing-Toolkit − javax.swing : Die Klassen von Swing − Vorteile: − Klassen werden eindeutig spezifizierbar durch Angabe des Packagenamens. − Die Daten innerhalb eines Packages werden zusätzlich gekapselt. − Es können zusätzliche Zugriffsberechtigung für Klassen innerhalb desselben Packages definiert werden. − Klassen desselben Package − werden im gleichen Directory gespeichert. − Der Name des Directorys muss gleich sein wie der des Package. − Deklaration: − Package-Deklaration muss als erstes Statement in jeder Klasse stehen: package mypackage; import java.applet.*; • Package-Namen − Beginnen normalerweise mit Kleinbuchstaben (häufig ganzer Packagename kleingeschrieben) − Sonst gelten die gleichen Regeln wie bei Klassennamen. − Packagenamen sollten internetweit eindeutig sein. − Vorschlag für internetweit eindeutige Package- Namen: Æ URL verwenden. − Damit würde eine Methode einer bestimmten Klasse folgendermassen eindeutig spezifiziert: firmenDomänenName.verzeichnis1.verzeichnis2.... ....packageName.KlassenName.methodenName Abstrakte Klassen, Interfaces etc.doc © 2010 InIT/ZHAW 11 − − − • • 2.3 • • Beispiele: com.sybase.jdbc.SybDriver ch.zhaw.huhp.meinPackage.GenialeKlasse Klassen ohne Package-Angabe − gehören zu einem anonymen Package. − Zu ihm gehören alle "anonymen" Klassen im gleichen File und im gleichen Directory. Welche Klassen soll man zu Packages zusammenfassen? − Es gibt keine Regeln über die Anzahl Klassen pro Package − Klassen die einander häufig brauchen, sollten im gleichem Package ablegt sein − Klassen, die häufig gebraucht werden, werden häufig in separate Packages abgelegt (Klassenbibliothek) Importieren von Klassen und Packages Generell muss jede Klasse, die verwendet wird, eindeutig mit dem vollen Package-Namen spezifiziert werden. Der volle Package-Name kann nur weggelassen werden, wenn die entsprechende Klasse mit einem import-Statement am Anfang der Datei importiert wird: − Beispiel: Wir möchten die Klassenmethode statMethode() der Klasse mypackage.MyClass aufrufen. − ohne import: mypackage.MyClass.statMethode(); − mit import: import mypackage.MyClass; ... MyClass.statMethode(); • Falls alle Klassen eines Packages importiert werden sollen: import mypackage.*; • Zur eindeutigen Spezifikation eines Packages muss der ganze Directory-Pfad des Package angegeben werden: Beispiel: • • import projects.myproject.mypackage; projects muss dabei ein Subdirectory eines Verzeichnisses im Classpath von Java sein. Die Punkte werden je nach Betriebssystem in „/“ oder „\“ übersetzt, um entsprechendes Directory zu finden. Die Packages im JDK beginnen mit − java (Standardklassen) − javax (Standard-Erweiterungsklassen des JDK) − org.omg (CORBA) Basis-Package java.lang − − wird automatisch importiert enthält die grundlegenden Klassen von Java. Abstrakte Klassen, Interfaces etc.doc © 2010 InIT/ZHAW 12 2.4 • • • • Sichtbarkeitsregeln für Packages Java definiert für Packages einen zusätzlichen Sichtbarkeitsbereich: Æ package. Dies ist die Standardsichtbarkeit in Java. Klassen, Methoden, Variablen mit package-Sichtbarkeit sind in jeder Klasse innerhalb des gleichen Packages sichtbar. Deklaration der package-Sichtbarkeit: int x; // ohne Sichtbarkeitsmodifikator Æ package-Sichtbarkeit Zusammenfassung aller Zugriffsmodifikatoren in Java gibt folgende Tabelle 1: Sichtbarkeit Zugriffsmodifikator gleiche Klasse gleiches Package Subklasse in anderem Package andere Klasse in anderem Package private ja nein nein nein keiner (d.h. package) ja ja nein nein protected ja ja ja nein public ja ja ja ja Tabelle 1: Zugriffsmodifikatoren in Java • Übung Studieren Sie das folgende Programm 1 und markieren Sie alle Zeilen, die einen Compiler-Fehler ergeben (weil eine Variable, Methoden oder Klasse) nicht sichtbar ist. package sicht1; import sicht2.*; public class Sichtbarkeit { public static void main(String[] args){ SamePackage same = new SamePackage(); PublicKlasse publicObj = new PublicKlasse(); PrivatKlasse privatObj = new PrivatKlasse(); SubOtherKlasse subOtherObj = new SubOtherKlasse(); System.out.println("a = "+ same.a); System.out.println("b = "+ same.b); System.out.println("c = "+ same.c); System.out.println("d = "+ same.d); System.out.println("Package sicht2"); System.out.println("a = "+ publicObj.a); System.out.println("b = "+ publicObj.b); System.out.println("c = "+ publicObj.c); Abstrakte Klassen, Interfaces etc.doc © 2010 InIT/ZHAW 13 System.out.println("d = "+ publicObj.d); System.out.println("SubOtherKlasse"); System.out.println("a = "+ subOtherObj.a); System.out.println("b = "+ subOtherObj.b); System.out.println("c = "+ subOtherObj.c); System.out.println("d = "+ subOtherObj.d); } } ------------------------------------------------------------------------------------------- neue Datei package sicht1; class SamePackage{ private int a = 1; public int b = 2; int c = 3; protected int d = 4; } ------------------------------------------------------------------------------------------- neue Datei package sicht1; class SubOtherKlasse extends PublicKlasse{ SubOtherKlasse(){ System.out.println("a = "+ a); System.out.println("b = "+ b); System.out.println("c = "+ c); System.out.println("d = "+ d); } } ------------------------------------------------------------------------------------------- neue Datei package sicht2; public class PublicKlasse{ private int a = 10; public int b = 11; int c = 12; protected int d = 13; } ------------------------------------------------------------------------------------------- neue Datei package sicht2; class PrivatKlasse{ private int a = 20; public int b = 21; int c = 22; protected int d = 23; } Programm 1: Sichtbarkeit Abstrakte Klassen, Interfaces etc.doc © 2010 InIT/ZHAW 14 2.5 • Professionelles Programmieren Wenn mehr als eine Klasse von einem Package importiert werden soll, importieren Sie das ganze Package mit einer Wildcard. Abstrakte Klassen, Interfaces etc.doc © 2010 InIT/ZHAW 15