public - TU Darmstadt

Werbung
Grundzüge der Informatik
Teil 2: Objektorientierte Programmierung
2.3 Modularisierung
Prof. Dr. Max Mühlhäuser
FG Telekooperation
TU-Darmstadt
Java-Pakete: Überblick
Pakete (Packages) ermöglichen:
• Bündeln von Klassen, die zu einem gemeinsamen
Aufgabenbereich gehören
• Vermeiden von potentiellen Namenskonflikten
– Klassennamen müssen innerhalb eines Pakets eindeutig sein
– Ein Klassenname kann in anderen Paketen erneut
verwendet werden
• Definition und Kontrolle von Zugriffen und
Sichtbarkeit
2003 © MM ...
GdI1 - 2.3: Modularisierung
2
Java-Pakete: Überblick
• Jede Klasse (und jede Schnittstelle) in Java ist Bestandteil
genau eines Pakets
– Ist eine Klasse (oder eine Schnittstelle) nicht explizit einem Paket
zugeordnet, dann gehört es implizit zu einem default-Paket
• Paket-Hierarchie
– Pakete sind hierarchisch gegliedert
à ein Paket kann Unterpakete besitzen, die selbst wieder in
Unterpakete aufgeteilt sind, usw.
• Punktnotation der Paketnamen
paket.unterpaket1.unterpaket11.Klasse
• Paketnamen sind sehr wichtig bei der Suche nach Klassen
2003 © MM ...
GdI1 - 2.3: Modularisierung
3
Java-Pakete
• Zu welchem Paket eine Klasse gehört, wird in der
zugehörigen .java-Datei bestimmt
• Der Quelltext eines gesamten Java-Programms kann
über mehrere Klassen und damit Dateien verteilt
sein
• Typdefinitionen einer Datei können auch zu
mehreren Programmen gehören (d.h. von ihnen
verwendet werden) à Wiederverwendung
2003 © MM ...
GdI1 - 2.3: Modularisierung
4
Java-Pakete
• Struktur einer .java-Datei:
Source-File = [Package-Declaration] {Import-Declaration}
{ Class-Definition | Interface-Definition }.
Package-Declaration = "package" Package-Name ";".
Package-Name = Identifier { "." Identifier }.
• Vor der Package-Declaration dürfen nur Kommentare und
Leerzeilen stehen
• Nur eine Package-Declaration pro Datei
• Wird die Package-Declaration weggelassen, ist die Datei
Element des Default-Pakets
2003 © MM ...
GdI1 - 2.3: Modularisierung
5
Java-Pakete
Paketdeklaration
• Der selbe Paketname kann in mehreren Dateien verwendet
werden
– Typdefinitionen, die zu einem Paket gehören, können somit über
mehrere Übersetzungseinheiten verteilt sein
à Kürzere Übersetzungszeiten
à Arbeitsaufteilung in großen Projekten wird unterstützt
• Paketname wird implizit jedem im Paket enthaltenen
Typnamen vorangestellt à Abtrennung durch einen Punkt
– Der vollständige Name einer Klasse ist
packagename.classname
2003 © MM ...
GdI1 - 2.3: Modularisierung
6
Java-Pakete
Import-Deklaration
Import-Declaration = "import" Package-Name "."
(Class-Name | "*") ";".
• Wird der Klassenname angegeben, kann auf diesen
künftig ohne Angabe des Pakets zugegriffen werden
• Wird * angegeben, können sämtliche im Paket
enthaltene Klassen ohne weitere Angabe des
Paketnamens verwendet werden
2003 © MM ...
GdI1 - 2.3: Modularisierung
7
Java-Pakete
Nutzen von Klassen eines anderen Pakets
• Volle Qualifizierung der Klasse, z.B.
java.util.Random einZufall = new
java.util.Random();
• import-Anweisung, z.B.
import java.util.Random;
...
Random einZufall = new Random();
2003 © MM ...
GdI1 - 2.3: Modularisierung
8
Java-Pakete
Nutzen von Klassen eines anderen Pakets
• import paket.* : alle Klassen des Pakets, z.B.
import java.util.*;
...
Random einZufall = new Random();
• Schlechter Stil: für Leser ist unklar, was gebraucht
wird
• Nur wenn (fast) alle Typdefinitionen eines Pakets
benötigt werden, ist die *-Form angebracht
2003 © MM ...
GdI1 - 2.3: Modularisierung
9
Import von Paketen
• Durch die Verwendung von Import-Anweisungen
können Namenskonflikte auftreten
– Existieren identische Typnamen in mehr als einer der
importierten Pakete, muss bei der Verwendung dieser
Namen immer das Paketpräfix benutzt werden, z.B.
import java.awt.*; // Enthaelt eine Klasse List
import java.util.*; // Enthaelt ebenfalls eine
// Klasse List
...
java.util.List list;
// Paketname verwenden um festzustellen,
// welche List verwendet wird
2003 © MM ...
GdI1 - 2.3: Modularisierung
10
Import von Paketen
• In jeder Datei werden einige Pakete automatisch
importiert:
– Das eigene Paket
– Das vordefinierte Paket java.lang
• enthält elementare Klassen wie z.B. Object, String
2003 © MM ...
GdI1 - 2.3: Modularisierung
11
Import von Paketen
• Zu Java gehören eine Vielzahl vordefinierter Pakete,
die mit dem JDK ausgeliefert werden, z.B.:
–
–
–
–
–
–
java.applet
java.io
java.net
java.util
java.util.zip
usw.
2003 © MM ...
Applet-Unterstützung
Ein- und Ausgabe für Dateien
Netzwerkprogrammierung
Hilfsklassen, z.B. Zufallszahlengenerator
Hilfsklassen zum Verwenden von .zip-Dateien
GdI1 - 2.3: Modularisierung
12
Paketbenennung
• Paketnamen spielen eine zentrale Rolle für die
Vermeidung oder Auflösung von Namenskonflikten
– sollten bedeutungstragend sein
– sollten möglichst eindeutig sein, am besten weltweit
• Konventionen zur Konstruktion weltweit eindeutiger
Paketnamen
– Der Paketname enthält als Präfix den Internet-DomainNamen der Hersteller in umgekehrter Reihenfolge
– Bindestriche sind in Paketnamen nicht erlaubt
– Beispiele
•
•
•
•
2003 © MM ...
URL der Firma Sun: sun.com
Klassen der Firma Sun: com.sun.paket1.paket11.Klasse
URL der TU Darmstadt: informatik.tu-darmstadt.de
Klassen der TU Darmstadt:
de.tudarmstadt.informatik.paket1.paket11.Klasse
GdI1 - 2.3: Modularisierung
13
Paketbenennung
Paketnamen und Dateisystemstrukturen
• Für die Zuordnung von Paketnamen zu Dateinamen müssen
Punkte im Paketnamen durch das Trennzeichen des
Betriebsystems ersetzt werden
– UNIX: / à Slash
– Microsoft-Betriebsysteme \ à Backslash
• Beispiel:
– Paketname: kilian.hobby.raytracer
– Zugehöriger UNIX-Verzeichnisname:
kilian/hobby/raytracer
– Zugehöriger Windows-Verzeichnisname:
kilian\hobby\raytracer
2003 © MM ...
GdI1 - 2.3: Modularisierung
14
Suche nach Paket- und Typnamen
• Ein Paketname wird als relativer Pfadname aufgefasst
• Die Betriebssystemvariable CLASSPATH definiert die
Verzeichnisse, ab denen ein Paketname gesucht wird
• Einträge in einer CLASSPATH-Spezifikation können
Verzeichnisse, ZIP- oder JAR-Dateien sein, die Klassen
enthalten
Trennt einzelne
Verzeichnisse
• Beispiel UNIX-Betriebssystem:
CLASSPATH=.:/home/joe/classes:/usr/local/classes.zip
• Beispiel Windows-Betriebssystem
set CLASSPATH=.;C:\joe\classes;D:\local\classes.zip
2003 © MM ...
GdI1 - 2.3: Modularisierung
15
Suche nach Paket- und Typnamen
• Die Verzeichnisse aus CLASSPATH sind die
Ausgangspunkte für den relativen Pfadnamen, der
über den Paketnamen festgelegt ist
• Die Verzeichnisse aus CLASSPATH werden in der
angegebenen Reihenfolge durchsucht (von links nach
rechts)
• Prinzipiell können mehrere Verzeichnisse existieren,
die über einen Paketnamen gefunden werden
können
– Keine gute Idee, da es dann von der in CLASSPATH
definierten Reihenfolge abhängt, welche Pakete (und damit
Typdefinitionen) tatsächlich verwendet werden
2003 © MM ...
GdI1 - 2.3: Modularisierung
16
Suche nach Paket- und Typnamen
• Eigene Pakete
– Der Compiler löst den hierarchischen Namen in
eine Kette von Unterverzeichnissen auf
– Am Ende der Kette liegt die Quelldatei
– Neben der Quelldatei wird auch die Klassendatei
in diesem Unterverzeichnis abgelegt
2003 © MM ...
GdI1 - 2.3: Modularisierung
17
Suche nach Paket- und Typnamen
• Der Java-Compiler übersetzt eingebundene Quelldateien, die
noch nicht übersetzt sind, automatisch mit, z.B.:
package mypackage;
import mypackage.subpackage.SomeClass;
class MainClass {
private SomeClass xy;
public static void main(String[] args) {
...
}
}
– Wird javac mypackage\MainClass.java aufgerufen, wird
automatisch auch mypackage\subpackage\SomeClass.java
compiliert
2003 © MM ...
GdI1 - 2.3: Modularisierung
18
Kapselung
Kapselung und Geheimnisprinzip (information hiding)
• Objekte kommunizieren miteinander über wohldefinierte Schnittstellen
• Jedes Objekt stellt den anderen Objekten nur die
nötige Menge an Operationen zur Verfügung
• Verdeckt hinter dieser Schnittstelle:
– die interne Struktur und die aktuellen Werte der Attribute
sowie die Implementierung der Operationen
Was geht Dich
meine Post an?
2003 © MM ...
GdI1 - 2.3: Modularisierung
19
Kapselung
• Mehr Abstraktion, einfacher von den Klienten zu
benutzen
– nicht geheim halten, sondern von unnötigen Details
befreien!
• Verhindert unerlaubte Zugriffe von kritischen Daten
• Anpassbarkeit
– Zugriff nur über öffentliche Methoden (Schnittstelle)
– Realisierung der Schnittstelle ist austauschbar, ohne
Änderungen in anderen getesteten und bewährten Klassen
nachzuziehen
2003 © MM ...
GdI1 - 2.3: Modularisierung
20
Kapselung
Eine Analogie
• Bankautomaten haben eine
Bedienungsschnittstelle
• Das Betätigen einer Funktionstaste z.B. „Auszahlung“ - entspricht dem
Aufruf einer Methode des
Bankautomat-Objekts
• Frau Schmidt ist der Sender und der
Automat der Empfänger
• Die Eingabe des Betrags entspricht
der Parametereingabe
2003 © MM ...
GdI1 - 2.3: Modularisierung
21
Kapselung
• Frau Schmidt sieht nur die
Bedienungsschnittstelle
• Sie hat keine Information darüber,
wie der Automat intern aufgebaut ist
• Für sie ist es unmöglich, den
Geldbehälter des Automaten
anzuschauen, ob genügend 50 EuroScheine darin enthalten sind, und
ihren Betrag selbst herauszuholen.
2003 © MM ...
GdI1 - 2.3: Modularisierung
22
Kapselung
• leichter zu verwenden
– Frau Schmidt möchte die Details der internen Realisierung
gar nicht wissen!
• verhindert unerlaubte Angriffe
– Nicht jeder sollte auf den Geldbehälter des Automaten
zugreifen können!
• schützt Klienten vor Veränderungen in der
Realisierung des Objektes
– Die Bank kann einen neuen Automaten aufstellen
– Solange die Bedienungsschnittstelle dieselbe bleibt, können
Kunden die neue Implementierung ohne weiteres benutzen
2003 © MM ...
GdI1 - 2.3: Modularisierung
23
Geheimnisprinzip
class Auto {
// Schnittstelle
public Auto(String farbe,
int geschwindigkeit,
int tankinhalt) {
this.tankinhalt = tankinhalt;
this.farbe = farbe;
this.geschwindigkeit =
geschwindigkeit;
. . .
} // end constructor
. . .
// Implementierung (Modell)
private int tankinhalt,
geschwindigkeit;
private String farbe;
. . .
} //2003end
class Auto
© MM ...
GdI1 - 2.3: Modularisierung
Schnittstelle
24
Geheimnisprinzip
class Auto {
// Schnittstelle
public Auto(String farbe,
int geschwindigkeit,
int tankinhalt) {
this.tankinhalt = tankinhalt
rfarbe
= rot(f);
= f; g = gruen(f); ...
this.geschwindigkeit =
geschwindigkeit;
. . .
} // end constructor
. . .
// Implementierung (Modell)
private int tankinhalt,
geschwindigkeit;
private int
String
private
r, g, farbe;
b;
. . .
} //2003end
class Auto
© MM ...
GdI1 - 2.3: Modularisierung
25
Geheimnisprinzip
class Auto {
// Schnittstelle
public Auto(String farbe,
int geschwindigkeit,
int tankinhalt) {
Änderung der
this.tankinhalt = tankinhalt
Implementierungsrfarbe
= rot(f);
= f; g = gruen(f); ...
entscheidung nach außen
this.geschwindigkeit =
geschwindigkeit;
nicht sichtbar
. . .
Alle Klienten können
} // end constructor
. . .
unverändert weiter
// Implementierung (Modell) verwendet werden
private int tankinhalt,
geschwindigkeit;
private int
String
farbe;
private
r, g, b;
. . .
} //2003end
class Auto
© MM ...
GdI1 - 2.3: Modularisierung
26
Geheimnisprinzip
Möglichkeiten zur Realisierung des Geheimnisprinzips
• Vertrauen: andere wissen, dass Geheimnisprinzip
eine gute Idee ist – sie sollten nur über Methoden
auf Daten eines Objekts zugreifen
– Aber: wenn das jemand nicht weiß?
– Versehentliche Zugriffe?
à Dokumentieren, welche Elemente wichtig sind
– Bösartige Zugriffe auf das Modell? (Grund für viele
Sicherheitslücken von Programmen)
à Programmiersprache muss Geheimnisprinzip
unterstützen
2003 © MM ...
GdI1 - 2.3: Modularisierung
27
Geheimnisprinzip
• Java bietet integrierte Sichtbarkeitsmodifikatoren
– Definieren Zugriffsrechte auf Elemente
– Die Programmiersprache erlaubt Zugriff auf Elemente nur
für Klassen, die auch dürfen
• In EBNF als Visibility geschrieben (siehe Teil 1.4, 2.1)
– Sowohl Methoden, Konstruktoren und Attribute als auch
Klassen können eine definierte Sichtbarkeit haben
– Modifikatoren für Methoden, Konstruktoren und Attribute
(Wiederholung):
"public" | "protected" | "private"
(oder kein Modifikator)
– Modifikatoren für Klassen (Wiederholung):
"public" (oder kein Modifikator)
2003 © MM ...
GdI1 - 2.3: Modularisierung
28
Zugriffsrechte und Sichtbarkeit
• implizit (Ohne Angabe eines Modifikators)
– Das Element ist nur innerhalb des Pakets sichtbar, in dem
die Klasse definiert ist
– Das gilt für Subklassen und Nicht-Subklassen
– Von außerhalb des Pakets ist kein Zugriff möglich
2003 © MM ...
GdI1 - 2.3: Modularisierung
29
Zugriffsrechte und Sichtbarkeit
• private: Nur Objekte der selben Klasse dürfen auf
das Element zugreifen
à weder andere Klassen, noch Erben
class A {
private void op1() { ... }
public void op2(A anAObject) {
... anAObject.op1(); ... // OK
}
}
2003 © MM ...
GdI1 - 2.3: Modularisierung
30
Zugriffsrechte und Sichtbarkeit
• protected: Alle Klassen im gleichen Paket dürfen
auf das Element zugreifen, sowie alle Klassen, die
davon erben (egal in welchem Paket definiert)
• public: Zugriff von überall erlaubt
2003 © MM ...
GdI1 - 2.3: Modularisierung
31
Zugriffsrechte und Sichtbarkeit
private
implizit
protected
public
Eigene
Klasse
2003 © MM ...
Erben im
gleichen
Paket
Im Paket
GdI1 - 2.3: Modularisierung
Erbe in
anderem
Paket
Im anderen
Paket
32
Zugriffsrechte und Sichtbarkeit
package
packageA;
A;
public
publicclass
classAA
AA{{
public
publicint
intone;
one;
int
inttwo;
two;
private
privatevoid
voidthree()
three(){{…
…}}
protected
protectedvoid
voidfour()
four(){{…
…}}
}}
package
packageA;
A;
class
classAB
AB {{
////one,
one,two,
two,four
four
}}
2003 © MM ...
package
packageA;
A;
class
classAC
ACextends
extendsAA
AA {{
////one,
one,two,
two,four
four
}}
package
packageB;
B;
class
classBA
BAextends
extends AA
AA{{
////one,
one,four
four
}}
package
packageB;
B;
class
classBB
BB{{
////one
one
}}
GdI1 - 2.3: Modularisierung
33
Zugriffsrechte und Sichtbarkeit
• UML-Darstellung von Sichtbarkeit
–
–
–
–
–
UML bietet die Sichtbarkeiten public, protected und private
public-Elemente werden durch ein + gekennzeichnet
protected-Elemente werden durch # gekennzeichnet
private-Elemente werden durch – gekennzeichnet
Keine Kennzeichnung der Sichtbarkeit = Sichtbarkeit
undefiniert
Klassenname
-privateAttribute : Klasse1
#protectedAttribute : int
+publicMethode(x: int) : boolean
2003 © MM ...
GdI1 - 2.3: Modularisierung
34
Zugriffsrechte und Sichtbarkeit
Zugriffskategorien beim Überschreiben
• Beim Überschreiben einer Methode wird die geerbte
Zugriffskategorie zunächst beibehalten
• Zugriffsrechte dürfen erweitert werden (z.B.
public anstelle von protected)
• Zugriffsrechte nicht eingeschränkt werden
• Grund für diese Regel: Ersetzbarkeit
– Daher muss die Subklasse nach außen hin mindestens alles
das zur Verfügung stellen, was auch ihr Vorfahr zur
Verfügung stellt
– Beim Überschreiben darf der Zugriff daher nicht weiter
eingeschränkt werden
2003 © MM ...
GdI1 - 2.3: Modularisierung
35
Zugriffsrechte und Sichtbarkeit
Zugriffskategorien beim Überschreiben
• private-Elemente, die in Unterklassen neu definiert
werden, dürfen eine beliebige Kategorie besitzen
– Grund: private-Elemente sind außerhalb der
definierenden Klasse nicht sichtbar
– Eine Subklasse sieht die Elemente nicht à es ist, als ob es
diese Elemente gar nicht gäbe
2003 © MM ...
GdI1 - 2.3: Modularisierung
36
Zugriffsrechte und Sichtbarkeit
Zugriffskategorien beim Überschreiben
• Methoden mit impliziter Zugriffskategorie können so
bleiben oder als protected oder public
überschrieben werden
• protected darf als public überschrieben werden
• public-Methoden müssen public bleiben
2003 © MM ...
GdI1 - 2.3: Modularisierung
37
Die Bedeutung der Zugriffsrechte
• Information Hiding (Parnas)
– Jedes Objekt enthält die Details seiner Realisierung
– Nach außen soll so wenig wie möglich von den Details der
Realisierung sichtbar sein
• Vererbung bricht Kapselung
– Ein Erbe übernimmt die Implementierung seiner Vorfahren
– Führt eine Abhängigkeit zwischen Ahnen und Erben ein
• Regel: es ist sinnvoll, so viele Attribute und
Methoden wie möglich mit dem Sichtbarkeitsmodifikator private zu deklarieren
2003 © MM ...
GdI1 - 2.3: Modularisierung
38
Mehrfachvererbung
• Bisher: Vererbung = Objektmodellierung mittels
hierarchischer Taxionomie
Lebewesen
• Was passiert, wenn mehrere verschiedene
Taxionomien verwendet werden sollen? …
Pflanzen
Spielgefährte
Haustier
Säugetiere
Hunde
Katzen
Haushund
• Lösung: Mit Mehrfachvererbung (Vielfachvererbung,
Multiple Inheritance) kann eine Subklasse die
Funktionalität mehrerer Basisklassen erben
2003 © MM ...
GdI1 - 2.3: Modularisierung
39
Mehrfachvererbung
• Bei Mehrfachvererbung erben die Subklassen die Eigenschaften und
Methoden aller Basisklassen
Angesteller
Studierender
personalNr : String
matrikelNr : String
geburtsdatum : Date
fachbereich : int
gehalt() : int
lerne()
alter() : int
HiWi
• Ein HiWi ist sowohl Angesteller als auch Studierender
–
–
–
–
Erbt die Eigenschaften personalNr und geburtsdatum von Angestellter
Erbt die Eigenschaften matrikelNr und fachbereich von Studierender
Erbt die Methoden gehalt() und alter() von Angestellter
Erbt die Methode lerne() von Studierender
• Ersetzbarkeit: Objekte der Klasse HiWi kann überall verwendet
werden, wo Objekte der Klasse Angesteller oder der Klasse
Studierender verwendet werden kann
2003 © MM ...
GdI1 - 2.3: Modularisierung
40
Mehrfachvererbung
Probleme bei Mehrfachvererbung
• Elemente mit gleichem Namen können in mehreren
Basisklassen vorkommen
– Beispiel: Angestellter und Studierender sollen je um ein Attribut
Name erweitert werden
Angesteller
Studierender
personalNr : String
matrikelNr : String
geburtsdatum : Date
fachbereich : int
name : String
name : String
gehalt() : int
lerne()
alter() : int
HiWi
• Welche Bedeutung hat HiWi.name ???
2003 © MM ...
GdI1 - 2.3: Modularisierung
41
Mehrfachvererbung
Probleme bei Mehrfachvererbung
• Sprachen mit Mehrfachvererbung bieten verschiedene
Strategien
1. Mehrfache Kopie und explizite Basisklasse (z.B. C++)
–
–
–
Die Subklasse erbt alle Elemente
Die Elemente mit Konflikten werden über den Namen der
Basisklasse unterschieden
Beispiel:
HiWi h = new HiWi();
h.Angestellter::name = "Name";
h.Studierender::name = "anderer Name";
–
à Attribute mit gleichem Namen können verschiedene Werte
haben
2003 © MM ...
GdI1 - 2.3: Modularisierung
42
Mehrfachvererbung
Probleme bei Mehrfachvererbung
2. Mehrfache Kopie und explizites Umbenennen (z.B. Eiffel)
–
–
–
Die Subklasse erbt alle Elemente
Bei Konflikten muss der Programmierer den problematischen
Elementen neue Namen geben
Beispiel (Java-ähnlich):
class HiWi extends Angestellter, Studierender {
rename Angestellter.name -> aName;
rename Studierender.name -> sName;
}
–
–
à Attribute erhalten neue Namen, können weiterhin
unterschiedliche Werte enthalten
Vorteil gegenüber 1 – Vererbungshierarchie ist nicht nach außen
sichtbar: kann geändert werden – Information Hiding!
2003 © MM ...
GdI1 - 2.3: Modularisierung
43
Mehrfachvererbung
Probleme bei Mehrfachvererbung
• 3. Einfache Kopie (z.B. C++)
–
–
–
Basisklassen haben ihrerseits eine gemeinsame Basisklasse à
Namen der Basisklasse werden mehrfach vererbt - Konflikt
Die Elemente mit Konflikten werden vereinigt, es gibt nur ein
Element
Person
Beispiel:
name : String
•
HiWi erbt name sowohl von
Angesteller als auch
Angesteller
von Studierender
personalNr : String
• Grund: beide erben
geburtsdatum : Date
von Person
gehalt() : int
à HiWi.name wird auf
alter() : int
Person.name abgebildet, ist eindeutig
–
Elegant, funktioniert aber nur
bei derartigen Gabelungen
2003 © MM ...
GdI1 - 2.3: Modularisierung
Studierender
matrikelNr : String
fachbereich : int
lerne()
HiWi
44
Interfaces
èMehrfachvererbung bringt Probleme, wenn ein
Element mehrfach benannt vorkommen kann
– Besonders konfliktträchtig: Attribute kommen mehrfach vor
• Java unterstützt keine Mehrfachvererbung von
Klassen mit Attributen
• Allerdings: mit Interfaces (Schnittstellen) kann man
ähnliche Effekte erzielen
2003 © MM ...
GdI1 - 2.3: Modularisierung
45
Interfaces
• Was sind Interfaces?
– definieren Dienstleistungen für andere Klassen, ohne die
Implementierung der Dienstleistungen festzulegen
• stellen funktionale Abstraktionen bereit, d.h.:
• legen das „Was“ fest, aber nicht das „Wie“
• nur das „Äußere“ einer Klasse, das ein Nutzer (Client) wissen
muss, nicht das „Innere“, das für Clients gemäß OOP ohnehin
„versteckt“ wird
– verhalten sich wie Klassen, die nur abstrakte Methoden
enthalten
UML
Notation
– Interfaces können von anderen
<<interface>>
Interfaces erben
• Zwischen Interfaces ist mehrfache
Vererbung möglich
2003 © MM ...
GdI1 - 2.3: Modularisierung
AnInterface
aMethod()
46
Interfaces
EBNF
Interface-Definition = ["public "] "interface " Interface-Name
[Interface-Extension] "{"
Interface-Body
"}".
Extension = "extends " Base-Interface {"," Base-Interface }.
Interface-Body = { ["public "] Method-Header ";" }.
2003 © MM ...
GdI1 - 2.3: Modularisierung
47
Interfaces
• Interfaces enthalten nur eine Schnittstellenbeschreibung
• Namenskonflikt zwischen Methoden von Interfaces
à implementierte Methode gilt alle deklarierenden
Interfaces
Beispiel
public interface AInterface {
public void methodA();
public void methodX();
}
public interface BInterface {
public void methodB();
public void methodX();
}
2003 © MM ...
GdI1 - 2.3: Modularisierung
48
Interfaces
Beispiel (fortgesetzt)
public interface ABInterface extends AInterface,
BInterface {
// enthält Methoden:
// void methodA() von AInterface
// void methodB() von BInterface
// void methodX() von AInterface und BInterface
}
2003 © MM ...
GdI1 - 2.3: Modularisierung
49
Interfaces
Implementierung von Interfaces
• Interfaces werden von Java-Klassen implementiert
• Wenn eine Klasse eine Schnittstelle implementiert,
dann muss sie alle Methoden der Schnittstelle
implementieren
– Ansonsten ist Klasse abstrakt, Unterklassen müssen
fehlende Methoden implementieren
• Auch leere Implementierungen sind erlaubt, z.B.
durch „{}“
2003 © MM ...
GdI1 - 2.3: Modularisierung
50
Interfaces
Implementierung von Interfaces - Notation
• Java: Interfaces werden nach dem „implements“
Schlüsselwort in der Klassendefinition angegeben
• UML: Durch
<<interface>>
gestrichelte Linie des
AnInterface
Vererbungspfeils
AnInterface wird
implementiert von
Klasse 1
Klasse1
2003 © MM ...
GdI1 - 2.3: Modularisierung
AnInterface wird
implementiert von
Klasse 2
Klasse2
51
Interfaces
Verwendung von Interfaces
• Verschiedene Java-Klassen können das selbe
Interface auf unterschiedliche Weise
implementieren
• Die Klienten-Klassen sprechen nur die
entsprechenden Klassen nur über das Interface an
• Die implementierenden Klassen können nach
Belieben verändert werden
– Die Schnittstelle des Interface bleibt unverändert à keine
Auswirkung auf Klienten-Klasse
2003 © MM ...
GdI1 - 2.3: Modularisierung
52
Interfaces
Verwendung von Interfaces
• Ein Interface kann wie eine abstrakte Klasse
verwendet werden
à Variablen mit einem Interface als Typ sind möglich
• Verfügbare Methoden: alle im Interface deklarierten
Methoden
• Prüfung, ob ein Objekt ein Interface implementiert:
mit dem instanceof-Operator
– anObject instanceof AnInterface ó anObject
gehört zu einer Klasse, die AnInterface implementiert
2003 © MM ...
GdI1 - 2.3: Modularisierung
53
Interfaces
Beispiel
• Das Interface Comparable stellt eine Methode zur
Verfügung, um zwei Objekte zu vergleichen
• compareTo nimmt einen Parameter vom Typ
Object und gibt zurück
– -1 oder kleiner wenn das implementierende Objekt kleiner
als der Parameter ist
– 0 wenn das implementierende Objekt gleich zum
Parameter ist
– +1 oder größer wenn das implementierende Objekt größer
als der Parameter ist
2003 © MM ...
GdI1 - 2.3: Modularisierung
54
Interfaces
Beispiel
Definition des Interfaces Comparable aus dem Java-Quelltext
/* This interface imposes a total ordering on
* the objects * of each class that implements
* it. */
package java.lang;
public interface Comparable {
/* Compares this object with the specified
* object for order. Returns a negative integer,
* zero, or a positive integer as this object
* is less than, equal to, or greater than the
* specified object. */
int compareTo(Object o);
}
2003 © MM ...
GdI1 - 2.3: Modularisierung
55
Interfaces
Beispiel
• Verwendung von Comparable in einer
allgemeinen Methode, die Elemente in eine
Liste sortiert einfügt
• Beispiel verwendet Klasse java.util.List
– Enthält mehrere beliebige Objekte
– Objekte werden über Index angegeben
– Index beginnt bei 0
2003 © MM ...
GdI1 - 2.3: Modularisierung
56
Interfaces
Beispiel
• java.util.List bietet Methoden
– int size()
// gibt die Anzahl der Elemente in der Liste zurück
– Object get(int index);
// liefert Objekt mit dem Index, der dem Parameter entspricht
– Beispiel: get(1) liefert
Objekt B
Objekt A
Objekt B
Objekt C
Index 0
Index 1
– void add(int index, Object element);
// fügt element am angegebenen Index ein
// alle nachfolgenden Elemente werden nach hinten geschoben
2003 © MM ...
GdI1 - 2.3: Modularisierung
57
Interfaces
Beispiel
import java.util.List;
/**
* Neue Klasse SortedList, die sortiert einfuegt
*/
public class SortedList {
private List elements = new List(); // leere Liste
/**
* Fuegt ein neues Element an die passende Position hinzu
* @param newElement das hinzuzufuegende Element,
*
darf nicht null sein
*/
public void add(Comparable newElement) {
if (newElement == null)
return; // tue nichts, wenn newElement null ist
int index = 0;
boolean stored = false;
// true, sobald newElement gespeichert ist
2003 © MM ...
GdI1 - 2.3: Modularisierung
58
Interfaces
Beispiel
while (index < elements.size() && !stored) {
Comparable testelement =
(Comparable)elements.get(index);
// Cast noetig, da get nur ein Object liefert
// wir wissen: alle Elemente sind comparable
// (es werden keine anderen hineingesteckt)
// das Element am Index ist groesser als das
// neue Element => Element auf diesen Index speichern
if (testelement.compareTo(newElement) > 0) {
elements.add(index, newElement);
stored = true;
}
index++;
}
2003 © MM ...
GdI1 - 2.3: Modularisierung
59
Interfaces
Beispiel
if (!stored)
// nicht gespeichert <=> newElement ist
// groesser als alle Eintraege von elements
// => speichern am Ende
elements.add(elements.size(), newElement);
} // end add
/**
* Gibt das Objekt am passenden Index zurueck
*/
public Object get(int index) {
return elements.get(index);
}
}
2003 © MM ...
GdI1 - 2.3: Modularisierung
60
Interfaces
Beispiel
public class Employee implements Comparable {
String lastName;
String firstName;
/** Employees werden nach Namen geordnet */
public int compareTo(Object obj) {
if (obj instanceof Employee) {
Employee empl = (Employee)obj;
int c = lastName.compareTo(empl.lastName);
// Strings enthalten bereits compareTo
// Wenn Nachnamen gleich, entscheidet der Vorname
if (c == 0)
return firstName.compareTo(empl.firstName);
else
return c;
} else
return -1 ;
}
...
}
2003 © MM ...
GdI1 - 2.3: Modularisierung
61
Interfaces
Beispiel
public class Point extends GraphicObject
implements Comparable {
double x, y ;
/** Points werden nach Abstand vom Ursprung geordnet */
public int compareTo(Object obj) {
if (obj instanceof Point) {
Point p = (Point)obj;
double dist = x*x + y*y;
double pDist = p.x*p.x + p.y*p.y;
if (dist == pDist)
return 0;
else
return dist < pDist ? -1 : 1;
} else
return -1 ;
}
...
}
2003 © MM ...
GdI1 - 2.3: Modularisierung
62
Interfaces
Beispiel
• SortedList kann sowohl Objekte vom Typ
Point als auch Objekte vom Typ Employee
sortiert speichern
• Änderungen am Quelltext der Klasse sind
nicht notwendig
• Point kann weiterhin ohne Probleme von
GraphicObject erben
2003 © MM ...
GdI1 - 2.3: Modularisierung
63
Herunterladen