Delphi-abstrakte Methoden

Diskutiere Delphi-abstrakte Methoden im Developer Network Forum im Bereich Hardware & Software Forum; Hi Was sind abstrakte Methoden? Welchen Unterschied macht es wenn ich eine Methode nur als virtual und nicht als abstract definiere? D.S.
  • Delphi-abstrakte Methoden Beitrag #1
D

Deep Space

Bekanntes Mitglied
Dabei seit
01.08.1999
Beiträge
2.004
Reaktionspunkte
0
Hi

Was sind abstrakte Methoden?
Welchen Unterschied macht es wenn ich eine Methode nur als virtual und nicht als abstract definiere?

D.S.
 
  • Delphi-abstrakte Methoden Beitrag #2
O

O Love

Bekanntes Mitglied
Dabei seit
08.04.1999
Beiträge
2.286
Reaktionspunkte
0
Abstrakte Methoden nimmst Du in Deinen Grundklassen. Da werden die Prototypen der Funktionen festgelegt, ohne Quelltext dazuzuschreiben. Du gibst halt als Schlüsselwort "abstract" bei der Klassendefinition an.

Wenn Du nun in den abgeleiteten Klassen vergißt, die abstrakten Methoden zu überschreiben, und rufst sie irrtümlicherweise auf, dann bekommst Du eine entsprechende Fehlermeldung.

"virtual" oder "dynamic" legt dann noch fest, ob die Funktionen geschwindigkeits- oder größenoptimiert werden sollen.

O Love

PS: Die Grundlagen der OOP (hier: Polymorphie) sind Dir aber klar?
 
  • Delphi-abstrakte Methoden Beitrag #3
D

Deep Space

Bekanntes Mitglied
Dabei seit
01.08.1999
Beiträge
2.004
Reaktionspunkte
0
Hi

Die Grundlagen OOP sind mir bekannt, und Polymorphy bedeutet doch in diesem Fall nur, dass erst während der Laufzeit die entprechende Methode anhand des Typs ausgewählt werden kann.

Nochmal zu abstract:
Was hat es denn für einen Vorteil wenn ich in der Grundklasse schon so einen "Prototyp" deklariere, aber noch keinen Quelltext dazu schreibe. Da kann ich doch gleich die Methode in der entsprechenden Nachfahr-Klasse implementieren, ohne sie mit abstract in der Grundklasse deklariert zu haben.

Virtual und dynamic werden doch nur dazu verwendet, Methoden zu erweitern. Also dass man die Methode der Vorgängerklasse noch mit inherited aufrufen kann?!

D.S.
 
  • Delphi-abstrakte Methoden Beitrag #4
O

O Love

Bekanntes Mitglied
Dabei seit
08.04.1999
Beiträge
2.286
Reaktionspunkte
0
Gut, dann bringe ich mal wieder das OOP-Beispiel der grafischen Objekte. Du deklarierst eine Grundklasse, TGraphObject. Davon leitest Du TGraphElli, TGraphRect und TGraphLine. Zu beachten ist, daß diese Klassen nur direkt von der Basisklasse abgeleitet sind.

In der Basisklasse hast Du nun die Zeichenmethode Paint deklariert, und zwar abstrakt. Warum? Weil Du noch nicht weißt, wie Du zeichnen sollst, aber der Rumpf der Funktion ist schon mal da. Warum das? Wenn Du jetzt eine Liste (oder Array) von TGraphObject hast, und diese Objekte zeichnen willst, dann brauchst Du die (abstrakte) Paint schon in der Basisklasse.

Dazu kommt noch, daß Du die Paint in der Basisklasse nicht nur abstrakt, sondern auch virtuell deklarieren mußt. Warum? Denn nur damit funktioniert die Polymorphie: Alle Deine Instanzen der Objekte sind kompatibel zu TGraphObject, und beim Aufruf der Paint nimmt er dann entsprechend der Klasse die "richtige" Paint.

O Love
 
  • Delphi-abstrakte Methoden Beitrag #5
D

Deep Space

Bekanntes Mitglied
Dabei seit
01.08.1999
Beiträge
2.004
Reaktionspunkte
0
Ok, das habe ich soweit verstanden, danke.

Jetzt ist mir noch etwas in Bezug auf virtual unklar. Ich habe eine Grundklasse(TFigur) in der eine Methode Init deklariert wird, als virtual. Jetzt wird in einer Nachfahrklasse(TRechteck) Init erneut deklariert, jedoch auch mit virtual. Mir ist nich klar wie das funktionieren kann. Die zweite Methode müsste doch als override deklariert werden?!

Die Klasse sieht folgendermaßen aus:

Code:
unit UFiguren;
{Version 1.1 vom 28.02.99, angepasst 18.01.2000}

interface
  uses UBunt, Forms, Graphics;


  TYPE
    TFigur = class(Tobject)
      protected
        hStift:TBuntstift;

        zx: real;
        zy: real;
        zLaenge: real;
        zFarbe : TColor;
        zFuellfarbe: TColor;


      public
        procedure init(pForm : TForm;px,py,pl : real;
                       pf,phf : Tcolor);                virtual;
        procedure Zeichne;                              virtual; abstract;
        procedure Loesche;                              virtual;
        procedure BewegeUm(pdx, pdy: real);             virtual;
        procedure BewegeBis(px, py: real);              virtual;
        procedure Aktiviere;                            virtual;
        procedure Deaktiviere;                          virtual;
        procedure SetzeRandFarbe(pf : TColor);          virtual;
        procedure SetzeFuellFarbe(pff : TColor);        virtual;
        procedure SetzeFuellMuster(pfm : TBrushStyle);  virtual;
        procedure AendereGroesse(pdg:real);             virtual;
        procedure SetzeRandDicke(pd:integer);           virtual;

        function  Getroffen (px, py: real): BOOLEAN;    virtual; abstract;
        function  GibX: real;                           virtual;
        function  GibY: real;                           virtual;

        destructor Destroy;                             override;
    end;

TRechteck = class(TFigur)
                  protected
                   zHoehe:real;
                  public
                   procedure Init(pForm:TForm;px,py,pl,ph:
                                  real;pf,phf:Tcolor);        virtual;
                   function getroffen (px,py: real): BOOLEAN; override;
                   procedure Zeichne;                         override;
                   procedure AendereGroesse(pdg:real);        override;
               end;

D.S.
 
  • Delphi-abstrakte Methoden Beitrag #6
O

O Love

Bekanntes Mitglied
Dabei seit
08.04.1999
Beiträge
2.286
Reaktionspunkte
0
Die zweite Methode müsste doch als override deklariert werden?!

Dieser Einwurf ist absolut korrekt. Deswegen liefert der Compiler auch eine Warnung (nicht nur einen Hinweis), die da lautet: "Methode 'init' verbirgt virtuelle Methode vom Basistyp 'TFigur'".

Ich vermute mal, Du hast Warnungen und Hinweise unter Projekt -> Optionen -> Compiler ausgeschaltet oder die Warnung übersehen. Tip, nein, eigentlich Pflicht: Anschalten und Quelltext solange umschreiben, bis keine Warnungen und keine Hinweise mehr angezeigt werden. Das verlangt u.U. nach mehr Code, man muß Variablen immer initialisieren, etc., aber es verhindert viele Fehler, die einem gar nicht so auffallen.

Weiter: Wenn Du nun "virtual" durch "override " ersetzt, wirst Du eine Fehlermeldung bekommen, daß sich die Deklaration von der vorherigen unterscheidet. Auch das ist korrekt, und ist nur durch "reintroduce" zu umgehen. Dies sollte man aber vermeiden, weil man an dieser Stelle die schöne Polymorphie durchbricht.

Weiter: Du kannst bei Deiner Basisklasse das Ableiten von TObjekt weglassen, da es sich ja hier um eigene Definitionen handelt. Ich vermute, Du willst das Abhandeln von Klassen zum ersten Mal richtig üben bzw. einsetzen. Durch TObjekt erbst Du einen ganzen Rattenschwanz an Methoden, den Du nicht brauchst.

Weiter: Es empfiehlt sich, jeder Klasse einen eigenen Konstruktor zu geben, in dem die Variablen mit Standardwerten initialisiert werden. Möglicherweise wird dadurch die Methode Init überflüssig.

Weiter: Der Zugriff auf die internen Variablen sollte immer über Methoden erfolgen (OOP-Stichwort: Kapselung). Ich sehe in Deinem Beispiel schon GibX und GibY. Delphi geht hier einen Schritt weiter und führt Properties mit read/write-Methoden ein. Kleines Beispiel:
Code:
  TTest	= class
  private
    FColor	: TColor;
    function	GetColor: TColor;
    procedure	SetColor (const Value: TColor);
  published
    property	Color	: TColor read GetColor write SetColor;
  end;
 
function TTest.GetColor: TColor;
begin
  // Einfachste Form ist das Zurückliefern des Wertes
  Result := FColor;
end;
 
procedure TTest.SetColor (const Value: TColor);
begin
  if (FColor = Value) then
    Exit;
  FColor := Value;
  // ... noch mehr machen
end;

Von außen kannst Du wie gehabt auf Color lesend und schreibend zugreifen, nur daß eben die entsprechenden Methoden dazu aufgerufen werden. Im Beispiel könnte bei der Klassendeklaration auch "... read FColor write SetColor" stehen, da lesend eh nur die private Variable zurückgeliefert wird, ohne daß irgendwelche Sachen gemacht werden. Schreibend siehst Du aber schon, daß bei gleichem Wert sofort rausgesprunden wird und eventuell nachfolgende Aktionen unterbunden werden.

Weiter: Deine ganzen Variablen sollten privat e werden (mit F davor, F wie Field). Du brauchst das protected nicht mehr, wenn Du in den abgeleiteten Klassen und von außen sowieso nur noch über die Properties zugreifst. Interne Methoden, wie die Zeichenroutine, greifen dann aber auf die klasseninternen und privaten Variablen direkt zu.

Weiter: Delphi hat eine Klassenvervollständigung eingebaut. In obigem Beispiel reicht es, wenn Du "property Color: TColor;" schreibst. Der ganze Schwanz an privaten Variablen, read-/write-Methoden und Rümpfe der Prozeduren wird durch gleichzeitiges Drücken der Tasten [Ctrl]+[Shift]+[C] eingefügt. Probiere es aus, das ist eine SUPER Funktion. Es klappt auch, wenn Du bei der Deklaration oben den Prototyp irgendeiner Methode schreibst. Beim Drücken der Tasten wird dessen Rumpf im Quelltext angelegt, und zwar an alphabetischer Stelle. Das klappt solange, wie sich die Implementierungen in richtiger Reihenfolge befinden, meistens wird es durch manuelles Einfügen durchbrochen.

Noch Fragen? :D Ich schlage vor, Du schreibst Deine Klassen erstmal ein wenig um und stellst diese (ohne Ausprogrammieren der Methoden) hier wieder rein. Oder Du schickst mir eine Mail, da können wir dann die Quelltexte austauschen...

O Love
 
  • Delphi-abstrakte Methoden Beitrag #7
D

Deep Space

Bekanntes Mitglied
Dabei seit
01.08.1999
Beiträge
2.004
Reaktionspunkte
0
Thx, das muss ich erst mal verarbeiten. In deiner Ausfürhrung ist eine ganze Menge womit ich noch nicht gearbeitet habe. Ich fange, wie du schon richtig vermutet hast, gerade erst an mich mit der Programmierung von Klassen näher zu beschäftigen.

Also wenn ich dich richtig verstanden habe, dann ist es nur nötig die Methode der Nachfolgerklasse mit virtual zu deklarieren, wenn sie sich von der Deklaration in der Vorgängerklasse unterscheidet. Dem zufolge wäre es dann ja theoretisch möglich der Methode "AendereGroesse" in "TRechteck" einen Parameter hinzuzufügen und diese dann als virtual zu deklarieren?! Müsste dann doch genauso funktionieren wie bei gleichen Parametern und override?!

Wenn man mit reintroduce eine virtuelle Methode verdeckt, kann dann auf diese noch mit inherited zugegriffen werden? Wenn nicht könnte man die Methode doch genau so gut statisch deklarieren.

D.S.
 
  • Delphi-abstrakte Methoden Beitrag #8
O

O Love

Bekanntes Mitglied
Dabei seit
08.04.1999
Beiträge
2.286
Reaktionspunkte
0
Halt, halt!

"virtual" (oder "dynamic") nimmst Du bei der ersten Einführung einer Methode, bei Dir also in der Basisklasse. Wenn Du diese dann in den abgeleiteten Klassen überschreibst, dann heißt das logischerweise "override". Und immer beachten, das Aussehen der Methode ändert sich nicht, damit die Polymorphie funktioniert.

Ich bereue hier und jetzt, Dir von "reintroduce" berichtet zu haben. :) Wie der Name schon sagt, führst Du damit ein neues Aussehen ein. Ab jetzt gilt dieses neue Aussehen. Wie Du schon angemerkt hast, macht man das gerne bei statischen Methoden, wie z.B. beim Konstruktor Create. Der Name bleibt, aber das Aussehen ändert sich.

Fazit: Verzichte erstmal auf das Init, führe eher einen Konstruktor ein, in dem Du dann alle Deine Variablen auf Standardwerte initialisierst:
Code:
constructor Create;

constructor TFigur.Create;
begin
  FFarbe := clWhite;
  FFuellfarbe := clWhite;
  ...
  // Bei Klassen werden übrigens alle Variablen zu 0 initialisiert.
  // Du brauchst hier also nur Variablen <> 0 reinschreiben.
end;

Desweiteren kannst Du ja mit den Properties anfangen. Die einfachste Art ist dabei, auf read-/write-Methoden ganz zu verzichten, also so:
Code:
property Color: TColor read FColor write FColor;
Übrigens, durch Weglassen einer der beiden Sachen (read oder write) kannst Du erreichen, daß eine Property nur zum Lesen (dies) oder nur zum Schreiben (eher selten bis gar nicht) geeignet ist.

O Love
 
  • Delphi-abstrakte Methoden Beitrag #9
D

Deep Space

Bekanntes Mitglied
Dabei seit
01.08.1999
Beiträge
2.004
Reaktionspunkte
0
Stimmt, war ein Denkfehler. Wenn ich die Methode nicht mit "override" überschreibe läuft das Ganze ja nicht mehr polymorph ab.

Dann werde ich mich als nächstes mal mit diesen Properties befassen.

Nochmal Danke für die vielen Hinweise!

D.S.
 
Thema:

Delphi-abstrakte Methoden

ANGEBOTE & SPONSOREN

https://www.mofapower.de/

Statistik des Forums

Themen
213.180
Beiträge
1.579.174
Mitglieder
55.879
Neuestes Mitglied
stonetreck
Oben