Waehrung - an der HTWG Konstanz

Werbung
Programmiertechnik
Vererbung & Polymorphismus für
Fortgeschrittene
Prof. Dr. Oliver Haase
Oliver Haase
Hochschule Konstanz
1
Motivation
Aufgabe: Finanzbuchhaltungssystem für internationale Hotelkette
 Problem: Hotels in verschiedenen Ländern rechnen mit
verschiedenen Währungen, die ineinander umgerechnet werden
müssen.
 Annahme: Abrechnungen erfolgen in US-Dollar.
 Problem: Umtauschkurs ändert sich jeden Tag!
 Beispiel: Hotel in Tokio hat eine Safe-Einlage im Wert von $25000.
Über Nacht steigt der Kurs des Yen um 10%  neuer Wert der
Safe-Einlage: $27500.
 Der Wert der Safe-Einlage darf nicht in US-$ gespeichert werden,
sondern muss dynamisch berechnet werden.
Oliver Haase
Hochschule Konstanz
2
Abstrakte Klassen
 Idee: Generalisiere von den konkreten Währungen, und führe eine
abstrakte Klasse Waehrung ein:
public abstract class Waehrung {
// gibt den Wert in US-$ aus
public abstract double dollarBetrag();
}
 Eine abstrakte Klasse kann abstrakte Methoden enthalten.
 Eine abstrakte Methode ist eine Methodendeklaration ohne
Implementierung. Jede Subklasse muss ihre eigene Implementierung
bereitstellen.
 Eine abstrakte Klasse kann nicht instantiiert werden!
Oliver Haase
Hochschule Konstanz
3
Abstrakte Klassen in UML
Waehrung
dollarBetrag:
double
 Merke: Die Namen abstrakter Klassen und Methoden werden kursiv
geschrieben.
Oliver Haase
Hochschule Konstanz
4
Abstrakte Klassen – Zweck
 Wozu sind abstrakte Klassen gut, wenn sie nicht instantiiert werden
können?
 Vererbung!
 Subklassen erben alle Eigenschaften der abstrakten Superklasse
 im Beispiel: alle Subklassen von Waehrung müssen die abstrakte
Methode dollarBetrag implementieren.
 D.h. die abstrakte Klasse Waehrung garantiert, dass alle
Subklassen die Methode dollarBetrag besitzen
(Schnittstellenvererbung)
Oliver Haase
Hochschule Konstanz
5
Klasse USDollar
 einfachste Währung ist US-Dollar, da keine Umrechung nötig ist:
public class USDollar extends Waehrung {
// Instanzvariable: Wert in US-$
private double wert;
public USDollar(double wert) {
this.wert = wert;
}
public double dollarBetrag() {
return wert;
}
}
Oliver Haase
Hochschule Konstanz
6
Klasse Yen
public class Yen extends Waehrung {
private static double kurs;
Klassenvariable, da Kurs
für alle Yen-Objekte gilt
und nur einmal
gespeichert werden muss
// Instanzvariable: Wert in Yen
private double wert;
public Yen(double wert) {
this.wert = wert;
}
public double dollarBetrag() {
return wert * kurs;
}
}
Wert wird in Yen gespeichert
Wert in US-$ wird
zurückgegeben.
public static void setKurs(double kurs) {
Yen.kurs = kurs;
}
Oliver Haase
Kurs kann klassenweit
aktualisiert werden
Hochschule Konstanz
7
Verwendung der Klasse Yen
 Tokioter Hotel hat eine Safe-Einlage von ¥ 2 000 000:
Yen safeInhalt = new Yen(2000000);
 Tauschkurs ändert sich auf 130 ¥ pro US-$:
Yen.setKurs(1.0 / 130);
 Aktuellen Wert des Safe-Inhalts in US-$ ausgeben:
System.out.println("Wert der Einlage in US-$: "
+ safeInhalt.dollarBetrag());
Konsole
Wert der Einlage in US-$: 15384.62
Oliver Haase
Hochschule Konstanz
8
Klasse Waehrung – Erweiterung
 Aufgabe: Berechnung der Steuer von 8% (veranlagt in den USA) für
das gesamte Barvermögen der Hotelkette.
 Idee: Implementiere diese Funktionalität als Klassenmethode der
abstrakten Klasse Waehrung:
public static double berechneSteuer(Waehrung[] geld)
{
double summe = 0.0;
for ( int i = 0; i < geld.length; i++ ) {
summe += geld[i].dollarBetrag();
}
return summe * 0.08;
}
Wie kann es ein Feld von Komponenten vom Typ Waehrung
geben, wenn Waehrung nicht instanziiert werden kann?
Oliver Haase
Hochschule Konstanz
9
Waehrung – Polymorphismus
 Antwort: Jede Subklasse von Waehrung, d.h. USDollar und Yen,
kann an die Stelle der Superklasse treten  Polymorphismus!
 Erklärung: Objekte vom Typ USDollar und Yen besitzen mindestens
alle Eigenschaften der Klasse Waehrung.
 Allgemein: Ein speziellerer Typ kann all das, was ein allgemeinerer
Typ kann.
 Speziellerer Typ wird implizit aufwärtskonvertiert in allgemeineren
Typ.
Oliver Haase
Hochschule Konstanz
10
Waehrung – Polymorphismus
 Beispiel:
Waehrung[] geld = new Waehrung[3];
geld[0] = new USDollar(2500);
geld[1] = new Yen(2000000);
geld[2] = new USDollar(20);
double steuer = berechneSteuer(geld);
 Beachte: Ein Objekt vom Typ USDollar kann an eine Variable vom
Typ Waehrung zugewiesen werden  US-$ ist eine (is-a) Währung.
Oliver Haase
Hochschule Konstanz
11
Objekttyp-Konversion
 Allgemeiner: Sei AllgemeineKlasse eine Superklasse von
SpezielleKlasse. Dann sind die folgenden Codezeilen zulässig.
AllgemeineKlasse a;
SpezielleKlasse s;
a = s;
und auch:
AllgemeineKlasse a = new SpezielleKlasse();
 Beachte: Java führt eine implizite Aufwärtskonversion für Objekttypen
durch, ähnlich der für skalare Typen. Diese kann auch explizit
angegeben werden:
AllgemeineKlasse a =
(AllgemeineKlasse) new SpezielleKlasse();
Oliver Haase
Hochschule Konstanz
12
Objekttyp-Konversion
 Auch eine explizite Abwärtstypwandlung ist möglich  Vorsicht: kann
zu Laufzeitfehler führen!
AllgemeineKlasse a = new SpezielleKlasse();
SpezielleKlasse s = (SpezielleKlasse) a;
OK
AllgemeineKlasse a = new AllgemeineKlasse();
SpezielleKlasse s = (SpezielleKlasse) a;
falsch!
Oliver Haase
Hochschule Konstanz
13
Objekttyp-Konversion
 Der Typ eines Objektes kann zur Laufzeit mit dem instanceofOperator geprüft werden:
Syntaxregel
<objectName> instanceof <KlassenName>;
 Die Operation liefert true, wenn das Objekt eine Instanz der
angegeben Klasse oder einer (direkten oder indirekten) Subklasse ist,
und false anderenfalls.
 Beispiel (Sichern einer Abwärtstypwandlung):
AllgemeineKlasse a = new SpezielleKlasse();
if ( a instanceof SpezielleKlasse)
SpezielleKlasse s = (SpezielleKlasse) a;
else
System.out.println(
"something went terribly wrong!");
Oliver Haase
Hochschule Konstanz
14
Waehrung – Polymorphismus
 Frage: Was passiert beim Aufruf von dollarBetrag() in der
Methode berechneSteuer()?
public static double berechneSteuer(
Waehrung[] geld) {
double summe = 0.0;
for ( int i = 0; i < geld.length; i++ ) {
summe += geld[i].dollarBetrag();
}
return summe * 0.08;
}
 Antwort: Für Objekte vom Typ USDollar wird die Methode
verwendet, die in der Klasse USDollar definiert wurde, und für
Objekte vom Typ Yen die Methode, die in der Klasse Yen definiert
wurde  späte Bindung (late binding).
Oliver Haase
Hochschule Konstanz
15
super
 Analog zu this gibt es auch ein Schlüsselwort super.
 Zur Erinnerung:
 this bezeichnet die aktuelle Instanz, für die gerade eine
Instanzmethode ausgeführt wird.
 Mit this.<KomponentenName> kann auf eine Instanzvariable
oder eine andere Instanzmethode zugegriffen werden.
 Als Methode – this(<Parameterliste>) – bezeichnet this
einen Konstruktor. Damit kann ein (spezieller) Konstruktor auf
einen (allgemeinen) Konstruktor zurückgeführt werden.
 Sehr ähnliches gilt für die super-Referenz und den superKonstruktor!
Oliver Haase
Hochschule Konstanz
16
super-Konstruktor
 Ein Konstruktor kann – und zwar nur in der 1. Zeile – einen Aufruf
des Konstruktors der Superklasse enthalten.
 Wenn das nicht der Fall ist, fügt Java automatisch den
parameterlosen Konstruktor der Superklasse ein.
public class NonsensDollar extends USDollar {
public NonsensDollar(double wert) {
super(wert);
}
public double dollarBetrag() {
überschreibt gleichreturn Math.random();
namige Methode der
}
Klasse USDollar.
}
Oliver Haase
Hochschule Konstanz
17
K‘tor - Ablaufdiagramm
Konstruktor
bearbeiten
Beginnt
K'tor mit
this?
ja
nein
Konstruktor der Superentsprechenden
klasse bearbeiten
Konstruktor bearbeiten
Initialisierer anwenden
Rumpf ausführen
Oliver Haase
Hochschule Konstanz
18
super-Referenz
 Die super-Referenz bezeichnet das aktuelle Objekt, jedoch als
Instanz der Superklasse betrachtet!
 Damit ermöglicht super Zugriff auf Komponenten (Variablen und
Methoden), die anderenfalls überdeckt und damit nicht sichtbar
wären:
public class NonsensDollar extends USDollar {
…
public double jetztMalImErnst() {
return super.dollarBetrag();
}
}
Oliver Haase
Hochschule Konstanz
19
Die Klasse Object
 Jede Klasse, die keine explizite Superklasse hat, ist automatisch
Subklasse von java.lang.Object.
 Damit ist letztendlich jede Klasse direkt oder indirekt Subklasse von
Object, und hat damit auch alle Eigenschaften der Klasse Object.
 Object definiert eine Reihe von Methoden. Die für uns
interessanteste ist  public String toString().
 Außerdem wird die gemeinsame Superklasse Object als
Elementtyp von Kollektionen verwendet.
Oliver Haase
Hochschule Konstanz
20
Die Methode toString()
 Die Methode toString() wird verwendet, um Objekte in eine
menschlich lesbare, textuelle Repräsentation zu bringen.
 Die Methode System.out.println() wendet auf alle
Objektparameter (außer Strings) vor dem Ausdrucken die Methode
toString() an. Der Code
Yen betrag = new Yen(200000);
System.out.println("Betrag: " + betrag);
ist gleichwertig zu:
Yen betrag = new Yen(200000);
System.out.println(
"Betrag: " + betrag.toString());
Oliver Haase
Hochschule Konstanz
21
Die Methode toString()
 Die Standardimplementierung der Klasse Object führt für zu einem
Ausdruck der Form:
Konsole
Betrag: Yen@18d107f
 Deshalb macht es Sinn, toString() geeignet zu überschreiben:
public class Yen extends Waehrung {
…
private double wert;
…
public String toString() { return wert + " Yen"; }
}
Konsole
Betrag: 200000.0 Yen
Oliver Haase
Hochschule Konstanz
22
Object für Kollektionen
 Die Superklasse Object kann verwendet werden, um Objekte
beliebigen Typs in Kollektionen (Mengen, Multimengen, Listen) zu
verwalten:
public class CircularArray {
private final static int SIZE = 100;
private int index;
private Object[] elements;
public CircularArray() {
elements = new Object[SIZE];
index = 0;
}
Oliver Haase
Hochschule Konstanz
23
Object für Kollektionen
}
public void add(Object element) {
elements[index] = element;
index = (index + 1) % SIZE ;
}
public Object pop() {
index = ( index > 0 ) ? index-1 : SIZE -1;
return elements[index];
}
Oliver Haase
Hochschule Konstanz
24
Object für Kollektionen
 Verwendung für Student –Objekte:
CircularArray array = new CircularArray();
Student studi1 = new Student();
studi1.setName("Karla Karlson");
studi1.setNummer(12345);
Student is-a Object
array.add(studi1);
Student studi2 = (Student) array.pop();
Typwandlung nötig, da popMethode Ergebnis vom Typ
Object liefert!
Oliver Haase
Hochschule Konstanz
25
Schnittstellen
 Aufgabe: Hotelkette besitzt neben Barvermögen (Objekte vom Typ
Waehrung) auch andere Arten von Vermögen:
 Grundstücke
 Aktien
 Firmenbeteiligungen
…
 Wir wollen sicher stellen, dass jeder Wertgegenstand seinen
monetären Gegenwert nennen kann.
 Lösungsmöglichkeit: Definition einer abstrakten Superklasse mit
einer abstrakten Methode, die alle Subklassen implementieren
müssen.
Oliver Haase
Hochschule Konstanz
26
Schnittstellen
 alternative Lösung: Java-Schnittstelle (Interface):
public interface Wertgegenstand {
public Waehrung wert();
}
 Schnittstellen sind Sammlungen von Instanzmethoden.
 Wie eine äußere Klasse wird auch eine Schnittstelle in einer
gleichnamigen .java-Datei gespeichert  Wertgegenstand.java.
 Zu Schnittstellen existieren keine Kindklassen, die die Schnittstellen
beerben (es gibt nichts zu erben!).
 Stattdessen kann eine Klasse eine Schnittstellen implementieren.
Dazu muss sie alle in der Schnittstelle deklarierten Methoden
definieren.
Oliver Haase
Hochschule Konstanz
27
Schnittstellen
 Beispiel:
public class Goldbarren implements Wertgegenstand {
public static double grammPreisInDollar = 60;
private double gewicht;
public Goldbarren(double gewicht) {
this.gewicht = gewicht;
}
public Waehrung wert() {
return new USDollar(gewicht *
grammPreisInDollar);
}
}
 Beachte: Goldbarren muss die Methode wert() definieren!
Oliver Haase
Hochschule Konstanz
28
Schnittstellen in UML
interface
Wertgegenstand
wert:
Waehrung
Goldbarren
Oliver Haase
Hochschule Konstanz
29
Schnittstellen
 Anwendung:
public static Waehrung gesamtwert(
Wertgegenstand[] objekte) {
double summe = 0.0;
for ( int i = 0; i < objekte.length; i++ ) {
summe += objekte[i].wert().dollarBetrag();
}
return new USDollar(summe);
}
 Schnittstelle Wertgegenstand wird verwendet wie eine Klasse,
siehe "Wertgegenstand[]".
 Das Feld objekte enthält Objekte, die die Schnittstelle
Wertgegenstand implementieren. Damit ist sichergestellt, dass
diese alle die Methode wert() definieren.
Oliver Haase
Hochschule Konstanz
30
Schnittstellen vs. Klassen
 Eine Klasse kann nur eine Superklasse haben  Einfachvererbung,
keine Mehrfachvererbung.
 Eine Klasse kann beliebig viele Schnittstellen implementieren.
 Eine Schnittstelle kann keine Methodendefinitionen enthalten.
 Eine abstrakte Klasse kann abstrakte sowie konkrete Methoden
enthalten.
 Eine Schnittstelle kann außer Konstanten keine Variablen enthalten.
 Eine Schnittstelle kann keine Klassenmethoden deklarieren.
Oliver Haase
Hochschule Konstanz
31
Time for a hot
cup of java!
Oliver Haase
Hochschule Konstanz
32
Herunterladen