Announcement

Collapse
No announcement yet.

Ableitung von Klassen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Ableitung von Klassen

    Hallo

    wer kann mir bei folgendem Problem helfen ?

    Da ich mehrere Formulare habe, die vieles gemeinsam haben, leite ich diese nicht gleich von TForm ab, sondern hab eine Basisklasse angelegt, von der die Formulare dann abgeleitet werden. Also in etwa so:

    <pre>
    class TBasisForm : TForm
    {
    // eigene Eigenschaften und Methoden....
    };
    </pre>

    <pre>
    class TForm1 : TBasisForm
    {
    // ...
    };
    </pre>

    <pre>
    class TForm2 : TBasisForm
    {
    // ...
    };

    // usw.
    </pre>

    Das Funktioniert auch alles ganz gut, ein Problem gibt es aber bei den IDE-Komponenten.

    Wenn ich beispielsweise bereits in TBasisForm einen Zeiger auf ein TButton haben will, hab ich dort angelegt, also:
    <pre>
    class TBasisForm : TForm
    {
    TButton* myButton;
    };
    </pre>

    Nun wird der Button in der abgeleiteten Klasse überschrieben:
    <pre>
    class TForm1 : TBasisForm
    {
    __published:
    TButton* myButton;
    // ...
    };
    </pre>

    so weit so gut, in der Basisklasse sind Operationen implementiert, die auf die Eigenschaften des Buttons zugreifen, der Compiler bringt auch keine Fehlermeldung. Leider haben die Operationen aber keine Auswirkungen auf diesen Button, egal ob ich den Zeiger in der Basisklasse unter protected, public, oder __published platziere. Kann mir jemand sagen wie ich so etwas realisieren kann ?

    Ich habe zwar eine etwas andere (mit ein bisschen mehr Aufwand verbundene) Lösung für mein Problem gefunden, ich hätte aber gerne diese hier, das müsste doch normalerweise funktionieren.

    Grüsse
    Sebastian

  • #2
    Hallo Sebastian,

    die Konstruktion kann so nicht funktionieren. Der Button in der Basisklasse ist gewissermaßen autark. Die Basisform weiß nichts von dem in der abgeleiteten Form nachträglich implementierten VCL-Element.
    Man müßte eine Rückwärtsverzeigerung im Konstruktor der abgeleiteten Form auf das Element in der Basisform
    machen,
    <PRE>
    TForm1:TForm1(void)
    {
    TBasisForm::myButton = myButton;
    .
    .
    }
    </PRE>
    was ich nicht für sehr elegant halte, weil man das erstens leicht vergessen kann und zweitens, was viel schwerer wiegt, man keinen Zugriff mehr auf die in der Basisform implementierten Methoden und Eigenschaften hat, den Vorteil, den man durch die Ableitung hat, also wieder aufgibt.

    Besser ist es doch, die benötigten Elemente (z.B. den Button) bereits in der Basisform anzulegen und die entsprechenden Methoden und Eigenschaften zu implementieren.
    In der abgeleiteten Form kann man dann veränderte Methoden und Eigenschaften überschreiben.

    Die beste Lösung ist es meiner Ansicht nach aber mit virtuellen Methoden zu arbeiten.
    In der Basisklasse wird z.B. die On-Click-Methode eines Buttons implementiert. Die spezifischen Dinge (z.B. Prüfungen) der abgeleiteten Form werden in einer virtuellen Methode implementiert, die in der Basisform nichts tut und von der Basisform aufgerufen wird.
    Gibt es in der abgeleiteten Form keine Spezialitäten, so braucht man die virtuelle Methode dort nicht zu implementieren. Es würde dann immer die leere virtuelle Methode aus der Basisform aufgerufen werden.

    Das Schlüsselwort virtual bewirkt das sogenannte späte Linken, so das zwar die OnClick-Methode aus der Basisform aufgerufen wird, aber die Spezialitäten der Form1 trotzdem ausgeführt werden, wenn das OnClick-Ereignis aus der Form1 kommt . Ohne virtual würde immer das TuWasBeiClick der BasisForm ausgeführt werden.

    Ein kleines Beispiel:
    <PRE>
    void __fastcall TBasisForm::ButtonClick(TObject *Sender)
    {
    // Aktionen die immer gelten z.B.
    taste = IDOK; // Es wurde ok gedrückt

    // Aufruf der Virtuelle Methode
    TuWasBeiClick(Sender);

    // evt. weitere Aktionen die immer gelten
    }
    </PRE>
    <PRE>
    void __fastcall TBasisForm::TuWasBeiClick(TObject *Sender)
    {
    // tut hier nichts
    }
    </PRE>
    Deklaration im Header:
    <PRE>

    <B>virtual</B> void __fastcall TuWasBeiClick(TObject *Sender);
    </PRE>
    Die Methode muß in der abgeleiteren Form exakt gleich implementiert werden:
    <PRE>
    void __fastcall TForm1::TuWasBeiClick(TObject *Sender)
    {
    // spezielle Funktionen für die Form1 z.B.
    taste = IDCANCEL;// Es wurde Cancel gedrückt
    }
    </PRE>
    Deklaration im Header:
    <PRE>
    <B>virtual</B> void __fastcall TuWasBeiClick(TObject *Sender);
    </PRE>
    Einfach mal ausprobieren und debuggen, dann versteht man am Besten, wie die Geschichte funktioniert.

    Ich habe mit dieser Methode eine ganze Hirarchie von MusterFormen aufgebaut und damit sehr große Projekte mit teilweise mehr als 400 Modulen entwickelt, die sehr schnell (auch von mehreren Leuten) entwickelt werden können und auch sehr gut funktionieren.

    mfg Lutz Hübschman

    Comment

    Working...
    X