Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Newbie sucht Hilfe - constructor vererben ?! (https://www.delphipraxis.net/5471-newbie-sucht-hilfe-constructor-vererben.html)

galaxy2k 7. Jun 2003 20:15


Newbie sucht Hilfe - constructor vererben ?!
 
Vorab , ich bin in der Oberstufe und noch ein relativer lamer in Delphi . Wir arbeiten gerade mit der Klasse mSum und Delphi 7.0 , um uns zu orientieren.

Zu meinem Problem :

Wir sollen ein Planetensystem programmieren. Im Prinzip kein Problem mit einer Kennt-Bezeihung zu realisieren . Jetzt kommt das große ABER :wink:

Wir haben eine Klasse namens mFigur . Dort wird der constructor defeniert und die Prozedur zeichne , loesche als privat ,sowie die Prozedur bewege als virtual/abstract deklariet .
Nun habe ich eine Klasse mSonne und eine mPlanet . mSonne ist einfach nur leer im Implementationteil und eine Klasse von mFigur .mPlanet dagegen soll mSonne kennen und ist eine Klasse von mFigur .

Mein Problem besteht jetzt darin , dass der constructor Teil von mFigur übernommen wird ,aber noch zusätzliche Parameter hinzugefügt werden in mPlanet . mPlanet muss ja mSonne kennen . Wie kann ich jetzt den alten constructor vererben ? Ich weiß wie das bei Prozeduren geht , mit Hilfe von inherited procedure_name , aber mir fehlt leider das KnowHow zur Zeit .



mfg R.K.


p.s. leider ist unser Lehrer nicht der beste in erklären :lol:

Motzi 7. Jun 2003 20:25

Ich hoffe ich hab dich richtig verstanden... ;)

Du kannst den geerbten Constructor auch einfach mit inherited [constructor] aufrufen (genauso wie bei andren prozeduren)...

galaxy2k 7. Jun 2003 20:34

Kann sein , dass ich doch was vergessen hab . Also , das alles soll sich im Interface abspielen und anschließend im Implementation-Teil von mPlanet für nähere Anweißungen.

Hier die Source-Beispiel:

mFigur
Delphi-Quellcode:
unit mFigur;

interface
uses mSum;
  type TFigur = class

  hatpen : buntstift;
  zXPos,zYpos,zGeschw,zRadius : Zahl;
  zFarbe : GanzeZahl;

[B] constructor init(pXpos,pYpos,pRadius,pGeschw:Zahl;pFarbe : GanzeZahl);virtual;[/B]

  procedure zeichne;
  procedure bewege;virtual;abstract;
  procedure loesche;

  destructor gibfrei;
end;
mPlanet
Delphi-Quellcode:
unit mPlanet;

interface
 uses mSum,mFigur,mSonne;
 type
  TPlanet = class(TFigur)

  hatpen : buntstift;
  Sonne : TSonne;
  zAbstand : Zahl;

  [B]constructor init(pSonne : TSonne; pAbstand : Zahl) ;override;[/B]
  procedure bewege;override;

  end;
Jetzt sollen natürlich die Parameter von mFigur vererbt werden ,damit ich mSonne in mPlanet benutzen kann und die Kennt-Beziehung vorhanden ist .


mfg R.K.


p.S. natürlich ist der Code in mPlanet falsch und so nicht complierbar :wink:

[edit=Daniel B]Delphi-Tags eingefügt. MfG Daniel B.[/edit]

Motzi 7. Jun 2003 20:43

Eine Methode kann nur überschrieben werden, wenn die neu implementierte Methode dieselben Parameter aufnimmt. Um in einer abgeleiteten Klasse eine Methode mit einem Namen einführen zu können, der in der Basis-Klasse schon einmal existiert braucht man "reintroduce".

JoelH 8. Jun 2003 08:33

hmm,
 
mal was leicht OffTopic, aber ich hab dazu ne Frage, kann man Constructoren vererben ? In C++ geht dass ja nicht. Wie auch immer, also ich mach es immer so dass ich den COnstructor überlade, also nicht über schreibe mit Override, sondern mit Overload überlade und dann mit inherited create(AOwner) den StandardKonstruktor der Klasse mit in meinen einbinde.

Motzi 8. Jun 2003 10:57

Schaut euch vielleicht mal meine Ausarbeitung über OOP in Delphi an: www.x-spy.net/personal

galaxy2k 8. Jun 2003 14:33

So wie JoelH geschrieben hat , meinte ich das . Denn mPlanet braucht den constructor von mFigur und zusätzliche Parameter (kenntSonne).



Mal sehen , ich werde es mal versuchen .


thx g2k

Christian Seehase 8. Jun 2003 16:55

Moin g2k,

da Du eine Pro Version hast, sind ja auch die Sourcen dabei.
Schau Dir da doch mal an, wie Borland das bei TThread gemacht hat.
Diese Kompo lebt praktisch davon, dass Du bei davon abgeleiteten Klassen einen anders strukturierten Constructor verwendest, als den der Basisklasse.

galaxy2k 14. Jun 2003 12:23

Danke für eure Hilfe . Hab es endlich geschafft . Mein Denkfehler war noch , dass der Init Teil im Implementation´bereich neu geschrieben werden muss usw. Seitdem luppt es wunderbar und ich hab wieder was dazugelernt .

Und nochmals danke für den Befehl overload .


mfg g2k

Jens Schumann 14. Jun 2003 15:28

Hallo galaxy2k,
Deine Klasse TFigur wird implizit von TObject abgeleitet. Dadurch hat sie schon einen constructor und einen destructor geerbt. Dadurch, dass Du Deinen constructor Init nennst, erhält Deine Klasse TFigur einen zweiten constructor (Klassen können beliebig viele constructoren haben). Wenn Du innerhalb der des constructors Init nicht inherited Create aufrufst begehst Du einen schweren Fehler. Das geleiche gilt für Deinen destructor gibfrei. Damit hast Du dann die "VirtualChain" unterbrochen und Deine Objekte werden nicht richtig erstellt bzw. abgeräumt.

Jens Schumann 14. Jun 2003 18:08

Hallo Motzi,
Deine Ausarbeitung beschreibt den Punkt Polymorphie nicht ganz richtig.
Das Polymorphie mit "Vielgestaltigkeit" übersetzt werden kann ist richtig. Was Du in Deiner Ausarbeitung unter Polymorphie beschreibst ist eher überschreiben o. ersetzten von Methoden und Eigenschaften.
Unter Polymorphie versteht man folgendes:
Schaun wir erstmal folgenden Source an
Delphi-Quellcode:
Type

  TAbstractBaseClass = class(TObject)
  private
  public
    procedure DoShowMessage; virtual; abstract;
  end;

  TFirstClass = class(TAbstractBaseClass)
  private
  public
    procedure DoShowMessage; override;
  end;

  TSecondClass = class(TAbstractBaseClass)
  private
  public
    procedure DoShowMessage; override;
  end;

...

procedure TFirstClass.DoShowMessage;
begin
  ShowMessage('TFirstClass');
end;

procedure TSecondClass.DoShowMessage;
begin
  ShowMessage('TSecondClass');
end;

...
procedure DoIt;
var
    F : TAbstractBaseClass;
    S : TAbstractBaseClass;
begin
  F:=TFirstClass.Create; // <- hier ist die Polymorphie !!!
  S:=TSecondClass.Create; // <- hier ist die Polymorphie !!!
  Try
  Finally
    F.Free;
    S.Free;
    end;
end;
TAbstractBaseClass ist unsere abstrake Basisklasse. Von dieser Klasse werden TFirstClass und TSecondClass abgeleitet. Erst in den Nachfahren wird die procedure DoShowMessage tatsächlich deklariert.
In der procedure DoIt werden jetzt die Instanzen F und S vom Type TAbstractBaseClass deklariert. Und jetzt kommt es: F wird als TFirstClass und S als TSecondClass erzeugt. Die Instanzen F und S vom Type TAbstractBaseClass können hier sowohl vom Type TFirstClass oder TSecondClass gestalt annehmen. Das ist Polymorphie.
Dadurch, dass in TAbstractBaseClass die Methode DoShowMessage als virtual erklärt wurde wird sie beim Create mit in die Virtuelle Methoden Tabelle (VMT) aufgenommen. Dadurch, das für jede Instanz beim Create eine eigene VMT erzeugt wird, ist sichergestellt, dass immer die richtige DoShowMessage Methode aufgerufen wird.

galaxy2k 16. Jun 2003 13:23

Also , die Units sehen bei mir so aus . Falls daran im Aufbau was falsch ist , bitte korrigiert mich .

mFigur(Basisklasse) :

Delphi-Quellcode:
unit mFigur;

interface
  uses mSum;
  type
   TFigur = class

   hatpen : buntstift;

   zXpos,zYpos,zGeschw,zRadius,zAbstand : Zahl;
   zFarbe : GanzeZahl;
   

   constructor init(pXpos,pYpos,pGeschw,pRadius,pAbstand : Zahl;pFarbe : GanzeZahl);virtual;


   procedure zeichne;
   procedure loesche;
   procedure bewege;virtual;abstract;

 destructor gibfrei;

end;
 implementation
 constructor TFigur.init(pXpos,pYpos,pGeschw,pRadius,pAbstand : Zahl;pFarbe : GanzeZahl);
 BEGIN
  hatpen := buntstift.init;



  zXpos := pXpos;
  zYpos := pYpos;
  zGeschw := pGeschw;
  zRadius := pRadius;
  zAbstand := pAbstand;
  zFarbe := pFarbe;
   //erste Anweisungen
   hatpen.setzeFarbe(zFarbe);
   hatpen.setzeFuellMuster(gefuellt);
   hatpen.hoch;
   hatpen.bewegeBis(zXpos,zYpos);
 END;

 procedure TFigur.zeichne;

  BEGIN
  hatpen.zeichneKreis(zRadius);
  END;


 procedure TFigur.loesche;
  BEGIN
  zeichne;
  hatpen.radiere;
  zeichne;
  hatpen.normal;
  END;

  destructor TFigur.gibfrei;
  BEGIN
   hatpen.gibFrei;
  END;

 end.
mPlanet :

Delphi-Quellcode:
unit mPlanet;

interface
 uses mSum,mFigur,mSonne;
 type
  TPlanet = class(TFigur)

  zJahr : Zahl;
  kSonne : TSonne;

 constructor init(pkSonne : TSonne;pAbstand,pGeschw,pRadius : Zahl;pFarbe: GanzeZahl);overload;

 procedure bewege;override;
end;

implementation
 constructor TPlanet.init(pkSonne : TSonne;pAbstand,pGeschw,pRadius : Zahl;pFarbe: GanzeZahl);
 BEGIN
  hatpen := buntstift.init;

  kSonne := pkSonne;
  zAbstand := pAbstand;
  zGeschw := pGeschw;
  zFarbe := pFarbe;
  zRadius := pRadius;
  zXpos := kSonne.zXpos;
  zYpos := kSonne.zYpos;

   hatpen.setzeFarbe(zFarbe);
   hatpen.setzeFuellMuster(gefuellt);
   hatpen.hoch;
   hatpen.bewegeBis(zXpos,zYpos);

 END;

  procedure TPlanet.bewege;

   BEGIN
   hatpen.bewegeUm(zAbstand);
   inherited zeichne;
   warte(10);
   inherited loesche;
   hatpen.bewegeUm(-zAbstand);
   hatpen.dreheUm(zGeschw);
    IF (hatpen.winkel = 360) OR (hatpen.winkel = 0 ) then zJahr := zJahr + 1 ;
   END;
end.
mSonne :
Delphi-Quellcode:
unit mSonne;

interface
  uses mSum,mFigur;
  type
   TSonne = class(TFigur)

  constructor init(pXpos,pYpos,pRadius : Zahl;pFarbe : GanzeZahl);overload;
  procedure bewege;override;
end;
  implementation
   constructor TSonne.init(pXpos,pYpos,pRadius : Zahl;pFarbe : GanzeZahl);
   BEGIN
    hatpen := buntstift.init;
    zXPos := pXpos;
    zYpos := pYpos;
    zRadius := pRadius;
    zFarbe := pFarbe;

   hatpen.setzeFarbe(zFarbe);
   hatpen.setzeFuellMuster(gefuellt);
   hatpen.hoch;
   hatpen.bewegeBis(zXpos,zYpos);
  END;

  procedure TSonne.bewege;
  BEGIN
   inherited zeichne;
  END;

end.
[edit=Daniel B]Delphi-Tags eingefügt. MfG Daniel B.[/edit]

Jens Schumann 16. Jun 2003 13:33

Hallo galaxy2k,
am 14.06.03 habe ich weiter oben etwas zum Thema constructor und destructor geschrieben. Das solltest Du unbedingt beachten !!!
Hinweis: Man muß nicht alle Properties über der constructor setzen.
Du kannst die Paramter auch als Properties deklarieren und setzen nach dem Du das Objekt erzeugt hast.

Motzi 16. Jun 2003 13:49

@Jens Schumann: Wenn du dir mal den constructor von TObject anschaust, dann wirst du sehen, dass dieser nur aus einem leeren Funktions-Rumpf besteht, also eigentlich nur ein Dummy-Existenz fristet. Sofern ein Objekt also nur von TObjekt abgeleitet ist, ist ein Aufruf von inherited nicht wirklich notwendig! In den meisten(!) andren Fällen jedoch schon (aber auch nicht immer)!


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:15 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz