2. Teil im PPT-Format

Werbung
Unter- und Oberklassen: Beispiel
type KFZ = class kennzeichen: String; ... end;
PKW = class(KFZ) tueren: integer end;
LKW = class(KFZ) nutzlast: integer end; ...
var k: KFZ;
p: PKW; ...
p := PKW.Create;
p.kennzeichen := "DD-XX 1"; p.tueren := 5;
k := p;
... Zugriff auf k.kennzeichen ...
• Jeder PKW ist ein KFZ: Die Zuweisung eines Objekts der
Unterklasse an eine Variable der Oberklasse ist zulässig.
• Bei der Zuweisung gehen keinerlei Informationen verloren, das
Objekt bleibt unverändert.
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Typanpassung
type KFZ = class kennzeichen: String; ... end;
PKW = class(KFZ) tueren: integer end;
LKW = class(KFZ) nutzlast: integer end; ...
var k: KFZ;
p: PKW; ...
p := PKW.Create;
p.kennzeichen := "DD-XX 1"; p.tueren := 5;
k := p; ...
... Zugriff auf k.tueren ... ->Fehlermeldung
... Zugriff auf (k as PKW).tueren
• Der "as" Operator dient zur Typanpassung innerhalb von
Klassenhierarchien.
– "k as PKW" ist vom Typ "PKW"
– Die Typanpassung kann fehlschlagen (Laufzeitfehler).
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Regeln zur Typanpassung
• Jedes Objekt hat immer eine eindeutige Klassenzugehörigkeit, die
sich von der Erzeugung bis zur Löschung nicht ändert.
• Einer Variable von einem Klassentyp K können Objekte der Klasse
K und jeder Unterklasse von K zugewiesen werden.
• Der Zugriff auf ein Datenfeld, eine Methode oder eine Eigenschaft
eines Objekts o ist nur möglich, wenn dies in der Klassendefinition
der Klasse von o vorgesehen ist.
• Wenn ein Objekt o1 von einer Unterklasse K1 einer Klasse K ist,
aber über eine Variable der Klasse K zugänglich ist, so kann o1
mittels des "as"-Operators (o1 as K1) auch wie ein Objekt der
Klasse K1 behandelt werden ("Typanpassung", "down-cast").
• Seien K1 und K2 verschiedene Unterklassen von K, o1 ein Objekt
der Klasse K1, das über eine Variable der Klasse K zugänglich ist.
Die Typanpassung "o1 as K2" führt zu einem Laufzeitfehler.
• Ein Test, ob ein Objekt o einer Klasse K zur Unterklasse K1 gehört,
ist mit "o is K1" möglich.
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Frühe und späte Bindung
• Frühe Bindung:
– Im allgemeinen wird die bei Eintreffen einer bestimmten Nachricht
aufzurufende Methode bereits zur Übersetzungszeit, abhängig von
der Klassenzugehörigkeit des angesprochenen Objekts, bestimmt.
• Späte Bindung:
– In manchen Fällen ist zur Übersetzungszeit nur eine Oberklasse des
zur Laufzeit angesprochenen Objekts bekannt. In diesem Fall kann
man die Wahl der aufzurufenden Methode von der erst zur Laufzeit
bekannten Unterklasse abhängig machen.
– Späte Bindung in Object Pascal:
"virtuelle Methoden", Schlüsselworte virtual und dynamic
(Unterschied zwischen virtual/dynamic nur in Optimierungen.)
– Deklaration von Methoden, die virtuelle Methoden (in Unterklassen)
"überdefinieren":
Schlüsselwort override
– Implementierung: Virtual Method Table (VMT)
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Polymorphie von Methoden (1)
type KFZ = class
kennzeichen: String; ...
procedure anmelden(k: KFZDaten); virtual;
end;
PKW = class(KFZ)
tueren: integer ...
procedure anmelden(k: KFZDaten); override;
end;
LKW = class(KFZ) nutzlast: integer ...
procedure anmelden(k: KFZDaten); override;
var k: KFZ;
p: PKW; ...
p := PKW.Create; ...
p.kennzeichen := "DD-XX 1"; p.tueren := 5;
k := p;
k.anmelden(...);
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Polymorphie von Methoden (2)
• Polymorphie:
– gleicher Methodenname in Ober- und Unterklasse
– semantische Ähnlichkeit (!) der Methodenrümpfe
– dynamische Auswahl der Implementierung
• Prinzip:
TObject
MethodenVererbung
KFZ
OperationenSuche zur Laufzeit
nach der speziellsten Version
("dynamisches Binden")
PKW
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
TObject
• Alle Klassen in Object Pascal sind implizit von der Basisklasse
TObject abgeleitet.
• Ungefähre Struktur:
TObject = class
constructor Create;
// Speicherplatzreservierung
// Festlegung der Adresse (Identität)
procedure Free;
//Aufruf von Destroy
//falls Adresse ≠ nil
destructor Destroy; virtual;
end;
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Konstruktoren für Unterklassen
• Möglichkeit 1: Standardkonstruktor (aus TObject) verwenden.
var obj: K;
obj := K.Create;
• Möglichkeit 2: Eigener Konstruktor.
type K = class(K0)
var X, Y: integer;
constructor Create(Xinit,Yinit: integer);
end;
constructor K.Create(Xinit,Yinit : integer);
begin
inherited Create;
X := Xinit; Y := Yinit;
end;
var obj: K;
obj := K.Create(10,20);
• Möglichkeit 3: Standardkonstruktor (aus TObject) verwenden und
eigene Initialisierungsprozedur ("Init").
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Destruktoren für Unterklassen
type K = class(K0)
var X, Y: integer;
constructor Create(Xinit,Yinit: integer);
...
destructor Destroy; override;
end;
• Regeln für Destruktoren:
– Immer indirekt über Free aufrufen (vermeidet Laufzeitfehler)
– Im Rumpf immer als letzte Aktion Destruktor der Oberklasse aufrufen.
destructor K.Destroy(Xinit,Yinit : integer);
begin
...
inherited Destroy;
end;
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Beispiel: Bauteileverwaltung
• Jedes Bauteil hat eine Bauteilnummer (Zeichenreihe) und einen
Preis (Ganzzahl).
• Bauteile können Elemente und Baugruppen sein. Eine Baugruppe
besteht aus mehreren Bauteilen.
• Für ein Element ist der Preis direkt festgelegt, für Baugruppen
berechnet er sich aus der Summe der Preise der enthaltenen
Bauteile.
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Klassenstruktur für Bauteile-Beispiel (1)
type TBauteil = class
bauteilNr: string;
function gibPreis: integer; virtual;
end;
TElement = class(TBauteil)
preis: integer;
constructor Create(n: string; p: integer);
function gibPreis: integer; override;
end;
TBaugruppe = class(TBauteil)
bauteile: array of TBauteil;
constructor Create(n: string);
procedure bauteilHinzu (b: TBauteil);
function gibPreis: integer; override;
function gibAnzahl: integer;
end;
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Abstrakte Methoden
• Methoden, für die keine Implementierung gegeben werden kann,
sondern die ausschließlich als Platzhalter für speziellere
Implementierungen dienen, werden "abstrakt" genannt.
– Schlüsselwort "abstract"
• Klassen, die abstrakte Methoden enthalten, heißen auch
"abstrakte Klassen".
• Beispiel:
– Was ist die Implementierung der Methode "gibPreis" für die
Oberklasse TBauteil?
type TBauteil = class
bauteilNr: string;
function gibPreis: integer; virtual; abstract;
end;
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Sichtbarkeit
• Öffentlich = public
• Privat = private
– Sichtbar in der aktuellen Unit
• Nur für Unterklassen = protected
– Auch sichtbar in Unterklassen in einer anderen Unit
• Geheimnisprinzip:
– Grundsätzlich sollte so viel wie möglich der in einem Objekt
gespeicherten Information als "privat" deklariert werden.
– Erhöhung der Wartungsfreundlichkeit und Stabilität.
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Klassenstruktur für Bauteile-Beispiel (2)
type TBauteil = class
public
bauteilNr: string;
function gibPreis: integer; virtual; abstract;
end;
TElement = class(TBauteil)
private
preis: integer;
public
constructor Create(n: string; p: integer);
function gibPreis: integer; override;
end;
TBaugruppe = class(TBauteil)
private
bauteile: array of TBauteil;
public
constructor Create(n: string);
procedure bauteilHinzu (b: TBauteil);
function gibPreis: integer; override;
function gibAnzahl: integer;
end;
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Implementierung Bauteile-Beispiel (1)
constructor TElement.Create(n: string; p: integer);
begin
bauteilNr := n;
preis := p;
end;
function TElement.gibPreis: integer;
begin
gibPreis := preis;
end;
constructor TBaugruppe.Create(n: string);
begin
bauteilNr := n;
end;
procedure TBaugruppe.bauteilHinzu(b: TBauteil);
begin
SetLength(bauteile,Length(bauteile)+1);
bauteile[High(bauteile)] := b;
end;
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Implementierung Bauteile-Beispiel (2)
function TBaugruppe.gibPreis: integer;
var i,p: integer;
begin
p := 0;
for i:=0 to High(bauteile) do
p := p + bauteile[i].gibPreis;
gibPreis := p;
end;
function TBaugruppe.gibAnzahl: integer;
var i,a: integer;
begin
a := 0;
for i:=0 to High(bauteile) do
if bauteile[i] is TBaugruppe then
a := a + (bauteile[i] as TBaugruppe).gibAnzahl
else a := a+1;
gibAnzahl := a;
end;
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Schichten-Architektur
Bauteile_U.pas
Benutzungsoberfläche
Bauteile_Modell.pas
Fachliches Modell
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Auszug aus "Bauteile_U.pas"
procedure TForm1.AbfrageClick(Sender: TObject);
var
bauteilNr: string;
b: TBauteil;
begin
if BauteilListBox1.ItemIndex <> -1 then begin
bauteilNr := BauteilListBox1.items
[BauTeilListBox1.ItemIndex];
b := findeBauteil(bauteilNr);
BauteilPreis.Text := IntToStr(b.gibPreis);
if b is TElement then
BauteilAnzahl.Text := '(keine)'
else
BauteilAnzahl.Text :=
IntToStr((b as TBaugruppe).gibAnzahl);
end
end;
Technische Universität Dresden
Prof. Hußmann
Informatik II (Maschinenwesen)
Herunterladen