AW: Übung Polymorphie
Danke Hoika, ja so funktioniert es.
Danke auch an Freimatz, vcl.dialogs habe ich aufgenommen, da ich eigentlich mit showmessage arbeiten wollte. Hat sich aber erledigt. Warum soll ich ausdrücklich "strict" private bzw. strict protected verwenden? reicht private bzw. protected nicht aus? was ist da anders bzw. besser? Danke DaddyH, das ist wesentlich einfacher und übersichtlicher. Warum bin ich nicht darauf gekommen? Ich habe mich von dem Gedöns Getter und Setter verleiten lassen. Aber so einfach funktioniert es auch einwandfrei und vermeidet Stolpersteine. Wieder ein kleines Problemchen gelöst. |
AW: Übung Polymorphie
Zitat:
|
AW: Übung Polymorphie
Genau das ist es. Das ist bei deinem Problem nur eine Kleinigkeit sollte man sich jedoch angewöhnen. Siehe auch: https://de.wikipedia.org/wiki/Datenk...rogrammierung)
|
AW: Übung Polymorphie
nun wollte ich das ganze vertiefen und habe dazu eine weitere class TTrapez (TDreieck) hinzugefügt. Für die Flächenberechnung wird nun zusätzlich zu SeiteA und SeiteB noch eine Höhe benötigt. Wenn ich nun in meiner Naivität einfach zur geerbten class TTrapez das Feld FHoehe und das Property Hoehe
hinzufüge im Glauben, dass ich zum Geerbten einfach noch die zusätzlich benötigten Felder und Propertys für eine erfolgreiche Programmausführung hätte, habe ich mich gründlich getäuscht, denn er findet die Poperty Hoehe in der Form nicht. Muss ich also diese Ergänzungen für die Flächenberechnung eines Trapezes in die Basisklasse TFigur aufnehmen damit ich weiter komme? Eigentlich wollte ich sehen wie es mit der Vererbung klappt, doch so würde ich zwar auch mit dem Ergebnis der Vererbung von der Basisklasse arbeiten. Schön wäre es, wenn ich mit dem Erbe von TDreieck und den zusätzlich benötigten Feldern arbeiten könnte. Liege ich da völlig falsch? Wie sollte ich das anstellen. Anbei die Auszüge aus der unit Berechnung und unit Form:
Delphi-Quellcode:
und die Form:
type TFigur = class(TObject)
private FSeiteA:Double; FSeiteB:Double; strict protected function getBerechneFl:Double;virtual;abstract; public property SeiteA:Double read FSeiteA write FSeiteA; property SeiteB:Double read FSeiteB write FSeiteB; property BerechneFl:Double read getBerechneFl; end; type TRechteck = class(TFigur) strict protected function getBerechneFl:Double;override; end; type TDreieck = class(TRechteck) strict protected function getBerechneFl:Double;override; end; type TTrapez = class (TDreieck) private FHoehe : Double; strict protected function getBerechneFl: Double;override; public property Hoehe :Double read FHoehe write FHoehe; end; implementation { TRechteck } function TRechteck.getBerechneFl: Double; begin result:=FSeiteA*FSeiteB; end; { TDreieck } function TDreieck.getBerechneFl: Double; begin result:=FSeiteA*FSeiteB/2; end; { TTrapez } function TTrapez.getBerechneFl: Double; begin result:=(SeiteA+SeiteB)/2*Hoehe; end; end.
Delphi-Quellcode:
procedure TForm1.btnDreieckClick(Sender: TObject);
var MyFigure: TFigur; begin MyFigure := TDreieck.Create; try MyFigure.SeiteA:=strtofloat(edtSeiteA.text); MyFigure.SeiteB:=strtofloat(edtSeiteB.text); lblErg.caption:=floattostr(MyFigure.BerechneFl) finally MyFigure.Free; end; end; procedure TForm1.btnEndeClick(Sender: TObject); begin close; end; procedure TForm1.btnFlClick(Sender: TObject); var MyFigure : TFigur; begin MyFigure := TRechteck.Create; try MyFigure.SeiteA:=strtofloat(edtSeiteA.text); MyFigure.SeiteB:=strtofloat(edtSeiteB.text); lblErg.caption:=floattostr(MyFigure.BerechneFl); finally MyFigure.Free; end; end; procedure TForm1.btnTrapezClick(Sender: TObject); var MyFigure : TFigur; begin MyFigure := TTrapez.create; try MyFigure.SeiteA:=strtofloat(edtSeiteA.text); MyFigure.SeiteB:=strtofloat(edtSeiteB.text); //MyFigure //Problem: findet Hoehe aus TTrapez nicht! lblErg.caption:=floattostr(MyFigure.BerechneFl); finally MyFigure.Free; end; end; procedure TForm1.FormCreate(Sender: TObject); begin edtSeiteA.text:=''; edtSeiteB.text:=''; end; end. |
AW: Übung Polymorphie
MyFigure ist als TFigur deklariert, deshalb kannst Du auch nur dessen Methoden und Eigenschaften direkt nutzen. Für spezifische Sachen musst Du typecasten.
Delphi-Quellcode:
procedure TForm1.btnTrapezClick(Sender: TObject);
var MyFigure : TFigur; begin MyFigure := TTrapez.create; try MyFigure.SeiteA:=strtofloat(edtSeiteA.text); MyFigure.SeiteB:=strtofloat(edtSeiteB.text); TTrapez(MyFigure).Hoehe := 20; // Um die Hoehe ansprechen zu können ist ein Cast notwendig lblErg.caption:=floattostr(MyFigure.BerechneFl); finally MyFigure.Free; end; end; |
AW: Übung Polymorphie
Danke DaddyH, es funktioniert.
Nur zum Selbstverständnis: wollte ich eine geerbte class TTrapez (TDreieck) um irgendwelche Felder und ggf. auch Methoden ergänzen, so müßte ich also die lokale Variable MyFigure als TTrapez deklarieren und könnte somit auf die Felder und Methoden zugreifen? Entspricht dies auch den guten Sitten der OOP? |
AW: Übung Polymorphie
Ja, wieso denn nicht? Der Cast wäre unnötig gewesen, wenn Du die lokale Variable gleich als TTrapez deklariert hättest, aber das wäre ja am Thema vorbei. Du kannst auch beispielsweise in Routinen, die eine TFigur als Parameter entgegennehmen, prüfen, ob es sich um eine spezialisierte Klasse handelt und sie dementsprechend behandeln.
Delphi-Quellcode:
Das kann aber leider auch sehr schnell zu sehr unübersichtlichem Code führen, in dem Fall sollte man vielleicht sein Klassendesign überdenken und/oder die Verwendung von Interfaces in Betracht ziehen.
procedure MachWas(Figur: TFigur);
begin if Figur is TTrapez then TTrapez(Figur).Hoehe := 20; end; |
AW: Übung Polymorphie
Statt diesem
Delphi-Quellcode:
würd' ich lieber das machen:
procedure TForm1.btnTrapezClick(Sender: TObject);
var MyFigure : TFigur; begin MyFigure := TTrapez.create; try MyFigure.SeiteA:=strtofloat(edtSeiteA.text); MyFigure.SeiteB:=strtofloat(edtSeiteB.text); TTrapez(MyFigure).Hoehe := 20; // Um die Hoehe ansprechen zu können ist ein Cast notwendig lblErg.caption:=floattostr(MyFigure.BerechneFl); finally MyFigure.Free; end; end;
Delphi-Quellcode:
Casten würd' ich in soeiner Situation:
procedure TForm1.btnTrapezClick(Sender: TObject);
var MyFigure : TTrapez; begin MyFigure := TTrapez.create; try MyFigure.SeiteA:=strtofloat(edtSeiteA.text); MyFigure.SeiteB:=strtofloat(edtSeiteB.text); MyFigure.Hoehe := 20; lblErg.caption:=floattostr(MyFigure.BerechneFl); finally MyFigure.Free; end; end;
Delphi-Quellcode:
function FlaecheBerechnen(Sender: TFigure) : Double;
begin if Sender is TTrapez then Result := TTrapez(Sender).BerechneFl else if Sender is TRechteck then Result := TRechteck(Sender).BerechneFl else if Sender is TDreieck then Result := TDreieck(Sender).BerechneFl else if Sender is TFigur then Result := TFigur(Sender).BerechneFl else Raise('unbekannte Figur'); end; // Aufruf: procedure TForm1.BtnBerechnenClick(Sender: TObject); begin MyFigure := TTrapez.create; // der gewünschte Typ, den könnte man z. B. über 'n TRadioGroup auswählen. try MyFigure.SeiteA := strtofloat(edtSeiteA.text); MyFigure.SeiteB := strtofloat(edtSeiteB.text); MyFigure.Hoehe := strtofloat(edtHoehe.text); lblErg.caption := floattostr(FlaecheBerechnen(myFigure)); finally MyFigure.Free; end; end; |
AW: Übung Polymorphie
Wozu die ganzen "Is"-Abfragen in FlaecheBerechnen, wenn eine TFigur-Instanz übergeben wird? Die angesprochene Methode ist virtuell, es sollte also immer die passende ausgeführt werden.
|
AW: Übung Polymorphie
Hast recht, wäre nur dann erforderlich, wenn sie nicht von einer Basisklasse abgeleitet wären.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:31 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz