Vorlesung Grundlegende Programmiertechniken

Werbung
Vorlesung 9. Sitzung
Grundlegende
Programmiertechniken
Wintersemester 2007/2008
Dozent
Nino Simunic
Computerlinguistik, Campus DU
Grundlegende
OOP Abstraktionsmittel: Fortsetzung
Programmiertechniken, WS 2007/2008
Abstrakte Methoden und Klassen
Interfaces
Unveränderbare Klassen(-elemente):
final
Abstrakte Klassen: Motivationsszenario (1)
Szenario: Speicherung verschiedenartiger geometrischer
Figuren in einem Array (, um später die Gesamtfläche zu
ermitteln). Umsetzung?
GeoFigur[]
GeoFigur[] fig
fig ==
{{ new
new Rechteck(),
Rechteck(),
…… }}
Rechteck
breite : double
hoehe : double
flaeche()
zeichnen()
-3-
GeoFigur
flaeche()
zeichnen()
Dreieck
s1 : double
s2 : double
s3 : double
flaeche()
zeichnen()
Abstraktion über
über
Abstraktion
Gemeinsamkeitenals
als
Gemeinsamkeiten
SuperklasseGeoFigur
GeoFigur
Superklasse
Kreis
radius : double
flaeche()
zeichnen()
Abstrakte Klassen: Motivationsszenario (2)
Was jedoch ist die allgemeinste/sinnvollste Implementierung,
welche in flaeche() in GeoFigur implementiert und später
vererbt werden sollte?
GeoFigur
Außerdem: Was überhaupt soll eine Instanz von GeoFigur
flaeche()
darstellen? Ein rundes zeichnen()
Rechtecksellipsendreieck?
Anscheinend gibt es keine eierlegende Wollmilchsau, welche
man als allgemeine Berechnung
für alle Formen vererben kann.
Dreieck
Rechteck
breite : double
hoehe
: double
Lösung
s1 : double
s2 : double
s3 : double
Kreis
radius : double
Lösung
DieMethode
Methodeflaeche()
flaeche()als
alsabstrakte
abstrakteMethode
Methode
flaeche()
Die
flaeche()
zeichnen()
flaeche()
deklarieren.Abstrakte
Abstrakte
Methodenenthalten
enthalten
deklarieren.
Methoden
zeichnen()
zeichnen()
keineImplementierung
Implementierung
undmüssen
müssenerst
erstin
in
keine
und
einer Unterklasse
Unterklasseimplementiert
implementiert werden.
werden.
einer
-4-
Abstrakte Methoden
abstract class GeoFigur {
// ^- Abstrakte Klasse
public abstract double flaeche();
// ^- Abstrakte Methode
// ...
} Deklaration
Deklaration abstrakter
abstrakter Methoden
Methoden via
via abstract
abstract
Modifikator:
Modifikator:
... abstract
abstract RÜCKGABETYP
RÜCKGABETYP METHODENBEZEICHNER();
METHODENBEZEICHNER();
...
Nur die
die Methodenköpfe
Methodenköpfe werden
werden definiert.
definiert.
-- Nur
Der Rumpf,
Rumpf, inkl.
inkl. {{ },}, sind
sind obligatorisch
obligatorisch wegzulassen.
wegzulassen.
-- Der
Eine Klasse
Klasse ist
ist abstract,
abstract, wenn
wenn sie
sie mindestens
mindestens
-- Eine
-5-
eine abstrakte
abstrakte Methode
Methode enthält.
enthält.
eine
Abstrakte Klassen/Methoden
Abstrakte Klassen können auch Datenfelder,
Konstruktoren, und nicht-abstrakte Methoden
enthalten.
public abstract
abstract class
class GeoFigur
GeoFigur {{
public
protected final
final java.awt.Color[]
java.awt.Color[] colors
colors == {{
protected
java.awt.Color.red,
java.awt.Color.red,
java.awt.Color.green
java.awt.Color.green
}; //...
//...
};
protected int
int figures;
figures;
protected
public GeoFigur(int
GeoFigur(int i)
i) {{
public
figures == i;
i;
figures
}}
abstract double
double flaeche();
flaeche(); //...
//...
abstract
}}
-6-
Methoden-Implementierung bei konkreter Subklasse
Konkrete Unterklassen einer abstrakten Klasse, müssen alle
abstrakten Methoden der Superklasse implementieren:
public class Kreis extends GeoFigur {
double flaeche() {
// flaeche = r^2 * pi ...
return flaeche;
}
void zeichnen() {
/* Nimm Zirkel... zeichne */
}
}
-7-
Methoden-Implementierung bei abstrakter Subklasse
Abstrakte Unterklassen einer abstrakten Klasse können,
müssen die abstrakten Methoden nicht zwingend
implementieren:
public abstract class Kreis extends GeoFigur {
public double flaeche(){
// Flächenberechnung... Rückgabe
}
abstract void zeichnen();
}
Redundant:
Redundant:Bereits
Bereitsso
sogeerbt.
geerbt.
-8-
Abstrakte Klassen: Instanzen?
Abstrakte Klassen sind nicht instanziierbar!
GeoFigur gf = new GeoFigur();
Eine Klasse kann auch abstrakt sein, wenn Sie
keine abstrakten Methoden enthält!
public abstract class NoObjects {
private int i; // ...
public static int getI(){ return i; } // ...
}
-9-
Referenzvariablen vom Typ einer abstrakten Klasse
Verwendung von Referenzvariablen vom Typ einer
abstrakten Klasse möglich
Jedoch nur Objekte von nicht abstrakten
Unterklassen:
-1010-
GeoFigur gf = new Kreis();
GeoFigur[] fig = new GeoFigur[3];
Berechnung der Gesamtfläche verschiedener Formen?
Wir haben:
Wir brauchen:
-1111-
Verschiedene Formen, aber
eine einheitliche Schnittstelle (flaeche()), um die
Fläche einer Form zu erhalten
Methode, welche ein Array mit Formen erhält, und die
Gesamtfläche berechnet
Wie sieht der Methodenkopf aus, wie sieht die
Berechnung aus?
Beispiel: Berechnung der Gesamtfläche von »Figuren«
public class FlaechenKalk {
public static double kalkFlaeche( GeoFigur[] figuren
double flaeche=0.0;
for (int i=0;i<figuren.length;i++){
flaeche += figuren[i].flaeche();
}
return flaeche;
}
public static void main(String[] args) {
GeoFigur[] figuren = new GeoFigur[3];
figuren[0] = new Kreis();
figuren[1] = new Dreieck();
figuren[2] = new Rechteck();
}
}
-1212-
){
Grundlegende
Programmiertechniken, WS 2007/2008
Interfaces
Interfaces
Dienen der ausschließlichen Beschreibung von
Eigenschaften
-1414-
Ähnlich abstrakten Klassen, jedoch …
Interfaces enthalten ausschließlich implizit
abstrakte und öffentliche Methoden, sowie
Konstanten
Interfaces werden von Klassen nicht geerbt,
sondern Klassen implementieren Interfaces
Deklaration eines Interface
Interfaces sind keine Klassen: Anstelle des
Schlüsselworts class verwenden sie interface
zur Deklaration:
public interface
interface MyInterface
MyInterface {{
public
}}
-1515-
Interfaces können weitere Interfaces erben
(extends), jedoch keine Interfaces
implementieren (implements)
Interfaces als Beschreibung von Eigenschaften
Durch das bloße Definieren eines Interfaces wird
die gewünschte Funktionalität nur beschrieben.
public interface
interface Groesse
Groesse {{
public
public int
int laenge();
laenge();
public
public int
int hoehe();
hoehe();
public
public int
int breite();
breite();
public
}}
-1616-
Soll diese von einer Klasse tatsächlich realisiert
werden, muss das Interface erst implementiert
werden!
Implementierung eines Interface
Implementierung wird durch die Erweiterung der classDefinition um eine implements-Klausel eingeleitet.
class Golfplatz
Golfplatz implements
implements Groesse
Groesse {{
class
// ...
...
//
}}
Die implementierende Klasse muss alle im Interface
definierten Methoden implementieren!
-1717-
Sonst: Implementierende Klasse muss sich und die nichtimplementierten Methoden als abstract deklarieren.
Implementierende Klasse erhält neuen Datentyp (den des
Interface, z.B. hier: Groesse)
Szenario: Transportmittel-Programm
Wir haben:
Wir brauchen:
Die auftank-Eigenschaft vererben.
Wir haben evtl. ein Problem:
-1818-
Eine Methode, um Transportmittel aufzutanken.
Eine einheitliche Schnittstelle zu den Transportmitteln,
um Sie auftanken zu können.
Mögliche Umsetzung:
Verschiedene Transportmittel in einer
Vererbungshierarchie.
Nicht alle Transportmittel lassen sich auftanken
(Fahrrad).
Szenario: Transportmittel-Hierarchie
Transport
buy()
Airplane
land()
Bicycle
pedal()
Car
drive()
Wewant
want to
toadd
addaamethod
methodcalled
called
We
()that
thatfills
fillsthe
thefuel
fueltank
tank
refuel()
refuel
of each
eachvehicle.
vehicle.
of
Theclass
classthat
that keeps
keepstrack
trackof
ofour
our
The
supplydepot
depot (SupplyDepot)
(SupplyDepot)will
will
supply
callthe
therefuel
refuelmethod
methodon
on
call
vehicleobjects.
objects.
vehicle
Whereisisthe
theright
right place
placeto
toadd
add
Where
refuel()in
inthe
thetree
treeof
of classes?
classes?
refuel()
Convertible
topDown()
-1919-
Saloon
fillRearSeat()
Transportmittel-Hierarchie: refuel()
refuel()
??
(1)
Transport
buy()
Airplane
land()
Bicycle
pedal()
Car
drive()
!!
!!
(1)We
Wecannot
cannot add
addaa
(1)
refuel()method
methodin
inthe
the
refuel()
Transportclass,
class,
Transport
becauseBicycle
Bicyclewould
would
because
inherit it,
it,and
andbicycles
bicycles are
are
inherit
not refuelled.
refuelled.
not
(2)We
Wecan
canadd
addthe
themethod
method
(2)
individuallyto
toAirplane
Airplane
individually
andCar
Car and
andany
anyother
other
and
unrelated Classes,
Classes, like
like
unrelated
Generator,which
which
Generator,
represent something
somethingyou
you
represent
canrefuel.
refuel.
can
refuel()
Convertible
topDown()
-2020-
Saloon
fillRearSeat()
(2)
SupplyDepot mit Implementierungsvariante (2)
SupplyDepot: Methode service(), um TransportmittelObjekte durch refuel()-Aufruf aufzutanken.
public class SupplyDepot {
public void service( ??? ) {
/* refuel() aufrufen */
}
}
What should be the type of the things we pass to it for
refuelling?
We cannot pass a Transport, because not all transport objects
have a refuel() method, and some non-Transport things (like
Generator or Pump) need refuelling.
-2121-
Denkbar: (a) Überladene service(), oder (b) instanceof in
einer service()-Methode
SupplyDepot
public class SupplyDepot {
public void service(Airplane a)
public void service(Car c)
public void service(Generator g)
public void service(Pump p)
// more methods, omitted
}
public class SupplyDepot {
{
{
{
{
/*
/*
/*
/*
more
more
more
more
code
code
code
code
*/
*/
*/
*/
}
}
}
}
Transport wäre hier
natürlich auch möglich.
public void service( Object refuelable )
{
if (refuelable instanceof Airplane ){
( (Airplane) refuelable ).refuel();
}
else if ( refuelable instanceof Car ) { /* ... */ }
// ...
} // ...
}
-2222-
(a)
(b)
Diskussion
Was aber, wenn bspw. ein auftankbares JetSki
hinzukommen soll?
SupplyDepot Modifizierung: Zusätzliches
instanceof oder neue Überladung (JetSki j).
Wünschenswert und effizienter:
-2323-
Möglich, aber insgesamt ineffizient »dank« schlechtem
Design
Zusätzliche Superklasse Refuelable gezielt vererben
an Car, Airplane, Generator, Pump, …
Refuelable-Klasse als zweite Superklasse?
class Refuelable
refuel()
buy()
Airplane
land()
Transport
Car
drive()
Bicycle
pedal()
Convertible
Saloon
Keine mehrfache
Klassenvererbung
via extends!
topDown()
-2424-
fillRearSeat()
Lösung?
Refuelable als Interface
public interface Refuelable {
void refuel();
}
Gewünschte Klassen (Car, Airplane, …) implementieren
Refuelable
public class Car extends Transport implements Refuelable {
// Mehr Code ...
public void refuel() {
// Implementierung: Tankdeckel abschrauben, …
} // Mehr Code ...
}
-2525-
Implementierende Klassen: Nun auch Datentyp
Refuelable. Konsequenz für SupplyDepot?
SupplyDepot nutzt Interface-Datentyp Refuelable
public class SupplyDepot {
// ...
public void service( Refuelable r )
r.refuel();
}
// ...
}
-2626-
{
Diskussion
Kommen nun zusätzliche Objekte (Schneemobil, Mofa, …), muss
SupplyDepot nicht mehr modifiziert werden!
Lediglich die neue Klassen müssen entsprechend deklariert werden
und sind sofort kompatible zu SupplyDepots
service()Methode:
public class Snowmobile implements Refuelable {
public void refuel() {
//...
}
// more methods, omitted
}
-2727-
Zusammenfassung (Hausaufgabe: Lesen, Fragen ggfs. notieren!)
The fundamental reason for interfaces is to allow classes to say, in
a way the compiler can check on it, "I have the behavior X, and you
can use one of my objects wherever you have something that
needs to do X".
In summary:
-2828-
Use the interface type as a parameter for a method M. Inside that method M,
you can call any of the methods promised by the interface parameter. When
you actually call the method M, you will have to provide an object that
implements the interface and thus has all the methods promised by the
interface.
Interfaces let you compile your code now. But you need to provide an object
with actual code for the thing to work at run-time.
The interface specifies the exact signatures of the methods that must be
provided by the implementing classes.
A class can extend only one superclass, but it can implement any number of
interfaces. Two interfaces can make the same demand for a method of a
given name in a class without. For example, interface A specifies a refuel()
method, interface B specifies a refuel() method, and class C implements both
interfaces.
Grundlegende
Programmiertechniken, WS 2007/2008
final
final
Elemente mit dem Schlüsselwort final können
nicht mehr weiter modifiziert werden: Klassen,
Methoden, Datenfelder
final vor Klassendefinition
final vor Methodendefinition
Die Methode kann in Subklassen nicht überschrieben
werden
final vor Attributen
-3030-
Von der Klasse können keine Subklassen gebildet
werden (Bsp. java.lang.String)
Der Wert des Attributs kann nicht verändert werden,
final dient also zur Deklaration von Konstanten
Illustration: final
class MyClass {
final int CONSTANT = 0;
public final void test() {
CONSTANT = 1;
}
Kompilierungsfehler
}
EinmaligeInitialisierung
Initialisierungim
im
Einmalige
Klassenrumpfoder
oder
Klassenrumpf
Konstruktor.
Konstruktor.
test()kannnicht
nichtmehr
mehr
test()kann
überschriebenwerden
werden
überschrieben
MyFinalClass kann
kannnicht
nicht
MyFinalClass
mehrvererbt
vererbtwerden
werden
mehr
final class MyFinalClass extends MyClass {
Kompilierungsfehlerbeim
beim
public void test() {
Kompilierungsfehler
Versuch,eine
einefinalfinalVersuch,
System.out.println("Hallo");
Methodezu
zuüberschreiben
überschreiben
Methode
}
}
class TestClass extends MyFinalClass {}
-3131-
Kompilierungsfehlerbeim
beim
Kompilierungsfehler
Versuch,eine
einefinal-Klasse
final-Klasse
Versuch,
abzuleiten
abzuleiten
Verwendete Literatur
-3232-
Bert Bates, Kathy Sierra. 2005. Head First Java,
2nd Edition. O'Reilly.
Guido Krüger. 2004. Handbuch der JavaProgrammierung, 4. Auflage. Addison Wesley
Peter van der Linden. 2004. Just Java™ 2, Sixth
Edition. Addison Wesley.
Hanspeter Mössenböck. 2005. Sprechen Sie
Java?, 3. Auflage. dpunkt.verlag
Patrick Niemeyer, Jonathan Knudsen. 2005.
Learning Java, 3rd Edition. O'Reilly
Herunterladen