![]() |
Aufruf abstrakter Methode führt zu Fehler
Hallo Gemeinde,
ich verstehe das Folgende nicht, und hoffe ihr habt eine Idee: Es kommt zum Fehler beim Aufruf einer abstrakten Methode.
Delphi-Quellcode:
In meiner Oberklasse TFahrzeug habe ich zwei Methoden als Abstract deklariert, da sie erst im Nachfahren implementiert werden soll. Im Nachfahren habe ich diese Methoden mit OVERRIDE überschrieben und implementiert -- dennoch kracht es nun beim Aufruf einer dieser Methoden: 'Abstrakter Fehler'.
TFahrzeug = CLASS(TObject)
... PROCEDURE Verzoegern; VIRTUAL; ABSTRACT; // Fahrzeugabhängig, daher abstrakt. PROCEDURE Beschleunigen; VIRTUAL; ABSTRACT; // Fahrzeugabhängig, daher abstrakt. END; TPKW = CLASS(TFahrzeug) PRIVATE PROTECTED PUBLIC PROCEDURE Verzoegern; OVERRIDE; PROCEDURE Beschleunigen; OVERRIDE; Ich sehe auch keine Warnung im Sinne von 'a verdeckt b'. Jemand eine Idee, was ich da falsch mache? Vielen Dank Jazzman |
AW: Aufruf abstrakter Methode führt zu Fehler
Welchen Vorteil erwartest Du denn von dem ABSTRACT ? Lasse das weg und mache leere Methode, die erst später konkret besetzt wird.
|
AW: Aufruf abstrakter Methode führt zu Fehler
Zitat:
Delphi-Quellcode:
in den Implementierungen auf? (auch wenn das keinen Sinn macht)
inherited Methodenname;
Folgendes Beispiel funktioniert solange man nicht ABSTRACTERROR definiert.
Delphi-Quellcode:
program Project1;
{$APPTYPE CONSOLE} {.$DEFINE ABSTRACTERROR} uses SysUtils; type TFahrzeug = class(TObject) procedure Verzoegern; virtual; abstract; procedure Beschleunigen; virtual; abstract; end; TPKW = class(TFahrzeug) public procedure Verzoegern; override; procedure Beschleunigen; override; end; { TPKW } procedure TPKW.Beschleunigen; begin inherited {$IFDEF ABSTRACTERROR}Beschleunigen{$ENDIF}; asm nop end; end; procedure TPKW.Verzoegern; begin inherited {$IFDEF ABSTRACTERROR}Verzoegern{$ENDIF}; asm nop end; end; var Fahrzeug: TFahrzeug; begin try Fahrzeug := TPKW.Create; try Fahrzeug.Beschleunigen; Fahrzeug.Verzoegern; finally Fahrzeug.Free; end; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; ReadLn; end. |
AW: Aufruf abstrakter Methode führt zu Fehler
Zitat:
Darüber muß ich nochmal nachdenken. :gruebel: Jazzman |
AW: Aufruf abstrakter Methode führt zu Fehler
Zitat:
Den Rest (Beispiel) verstehe ich nicht. :pale: Trotzdem Danke Jazzman |
AW: Aufruf abstrakter Methode führt zu Fehler
Zitat:
Wenn man eine Klasse schreibt, deren Elternklasse TPerson die abstrakte Methode aufDenKopfStellen hat, sollte man diese Methode implementieren, denn irgendwo gibt es Code, der sich darauf verlässt, das sich das Objekt auf den Kopf stellt (egal wie es das anstellt!), wenn diese Methode aufgerufen wird. Wenn die Methode in der Elternklasse einfach leer gelassen würde, wäre das nicht ersichtlich. So würde der Code, der dem TPerson-Objekt ein paar warme TSocken anziehen soll, diesem die eventuell über die Ohren ziehen, weil sich das Objekt nicht ordnungsgemäß mit den Füßen nach oben auf den Kopf gestellt hat :drunken: Und das würdest du beim Kompilieren dann nicht merken. |
AW: Aufruf abstrakter Methode führt zu Fehler
Zeig mal den Methodenaufruf. Bist du dir sicher, dass du das richtige Objekt instanziiert hast und die richtige Methode aufrufst?
mfg Christian |
AW: Aufruf abstrakter Methode führt zu Fehler
Zitat:
Deshalb mein Vorschlag, die Methode als leeren Rumpf zur Verfügung zu stellen und nicht nur zu deklarieren. Unterschied ist :
Delphi-Quellcode:
und
virtual; abstract
Delphi-Quellcode:
machen beide nichts, was nicht implementiert ist. Kommt "abstract" zusätzlich ins Spiel, dann wird wie gesagt, nichts gemacht, ausser zusätzlich eine Fehlermeldung zu produzieren.
virtual;
|
AW: Aufruf abstrakter Methode führt zu Fehler
Ich glaube, ich habe mich etwas schwammig ausgedrückt.
Zitat:
Wenn ich einen abstrakten Fehler bekomme, habe ich dann die Wahl:
Ohne abstract hätte ich nicht mitgekriegt, das überhaupt etwas schief laufen könnte. |
AW: Aufruf abstrakter Methode führt zu Fehler
Zitat:
Eine Art Documentation by Design |
AW: Aufruf abstrakter Methode führt zu Fehler
:thumb:
|
AW: Aufruf abstrakter Methode führt zu Fehler
Und noch mehr: Man erhält i.d.R. eine Warnung zur Compiletime (in anderen Sprachen sogar einen Fehler). Das hilft Bugs gar nicht erst entstehen zu lassen.
Das mit den leeren Methoden kann auch seinen Sinn haben. Wenn diese von anderen (nicht abstrakten) Methoden aufgerufen werden, wären das dann so genannte HookMethods. Also quasi Stellen, in die ich Code einfügen kann, aber nicht muss. Abstrakte Methoden sind hingegen eher TemplateMethods. Hier *muss* ich etwas implementieren. Beides braucht man oft, wenn man n Framework schreibt. Abstrakte Methoden, die nicht unbedingt intern aufgerufen werden, gibt es auch sehr oft in Klassen, die die Anwendungsdomäne modellieren. In leeren Methoden, die keine HookMethoden sind, sehe ich momentan keinen sonderlichen Sinn. Fällt euch einer ein? Fakt ist, dass die Exception "Abstrakter Fehler" auf einen Bug hindeutet. Man könnte die Exception unterdrücken, wenn man ne leere Methode dafür einsetzt. Der eigentliche Bug wird dadurch aber nicht behoben... mfg Christian |
AW: Aufruf abstrakter Methode führt zu Fehler
Eine relativ simple Klasse die man sich als Beispiel dazu anschauen kann ist
![]() ![]() |
AW: Aufruf abstrakter Methode führt zu Fehler
Zitat:
Zitat:
Delphi-Quellcode:
Alternative : nur "abstract" deklarieren und es kommt das:
showmessage ('Funktion kommt mit nächster Version');
Zitat:
|
AW: Aufruf abstrakter Methode führt zu Fehler
@Hansa ich weiß nicht wo du bist, wir sprechen hier über virtal abstract und da gibt es einen Compiler-Fehler wenn nicht deklariert wurde.
Vielleicht hast du dich ja im Thread geirrt Ach, das mit der Dokumentation meine ich nicht als Doku für den Enduser sondern für den Entwikler der eine Basisklasse erweitern möchte/soll/muss. |
AW: Aufruf abstrakter Methode führt zu Fehler
Zitat:
Delphi-Quellcode:
ABSTRACT alleine geht überhaupt nicht !
type
TKlasse1 = class procedure test; virtual; abstract; end; TKlasse2 = class (TKlasse1) procedure test; end; var Klasse1 : TKlasse1; Klasse2 : TKlasse2; Zitat:
Delphi-Quellcode:
aber nicht deklariert ist (in der Klassen-Definition), dann ist die Prozedur erstens "unknown identifier" und zusätzlich kommt noch "Ungenügende Forward- oder External-Deklaration". Ist die Prozedur deklariert mit ABSTRACT, dann reicht das. Mehr geht nicht mal (insbesondere keine konkrete Implementierung). Dann kommt nämlich hier :
type
TKlasse1 = class procedure test; virtual; abstract; end; var Klasse1 : TKlasse1; procedure TKlasse1.UndeklarierteImplementierung; begin end;
Delphi-Quellcode:
dieser Compilerfehler :
procedure TKlasse1.test;
begin ShowMessage(''); end; Zitat:
Delphi-Quellcode:
nicht implementiert werden, man kann im Programm trotzdem auf diese Prozedur zugreifen und produziert damit erst zur Laufzeit einen Fehler. Trotz des Fehlers lässt sich eine EXE erstellen, die lauffähig ist und eben Fehlermeldungen produziert. So richtig nach dem Motto : "es compiliert, wir können ausliefern". :mrgreen:
procedure TKlasse1.Test;
|
AW: Aufruf abstrakter Methode führt zu Fehler
Hallo,
bei neueren Delphi-IDEs kann man Warnungen des Compilers über die Projektoptionen in Fehlermeldungen umwandeln (Delphi-Compiler -> Hinweise und Warnungen: "Ausgabewarnungen"). Für ältere IDEs stellen die ![]() Gruß Hawkeye |
AW: Aufruf abstrakter Methode führt zu Fehler
Hansa's Ansatz bedeutet einfach: "Die Methode kannst Du überschreiben, musst Du aber nicht". Der 'abstract' Ansatz bedeutet einfach: "Du musst die Methode noch überschreiben".
Schön wäre es, wenn der Compiler beim abstract-Ansatz wirklich einen Fehler moniert. Leider macht er das wohl nicht, aber man kann sich auch so herausreden, das ein guter Entwickler sowieso eine umfangreiche Test-Unit mit seiner Klasse ausliefert, die dann auf nicht implementierten Methoden prüft. Ansonsten rennt ihr euch hier in Klugscheißerei fest, wenn ihr so weiter macht. Bisher ist davon natürlich weit und breit nichts zu sehen.:mrgreen: |
AW: Aufruf abstrakter Methode führt zu Fehler
Zitat:
Delphi-Quellcode:
ja nichts da. Beim Debugger gehts dann weiter. Wo soll denn der anhalten ?
virtual; abstract;
Mir wirds aber auch zu blöd. Wer unbedingt unnötige Fehlermeldungen im eigenen Programm haben will, der soll die Implementierung (auch wenn sie leer sein sollte) eben einfach weglassen. |
AW: Aufruf abstrakter Methode führt zu Fehler
Eine Klasse ist abstrakt, wenn sie entweder selber abstrakte Methoden deklariert oder solche von einer Elternklasse erbt, aber nicht selbst implementiert (überschreibt).
Da das Deklarieren einer abstrakten Klasse an sich nichts Verwerfliches ist, gibt der Compiler natürlich keine Warnung aus, wenn er eine solche findet. Die Warnung kommt erst dann, wenn man versucht, eine abstrakte Klasse zu instanziieren.
Delphi-Quellcode:
program AbstraktTest;
{$APPTYPE CONSOLE} uses SysUtils; type TAbstraktBasis = class(TObject) // Abstrakte Klasse, da abstrakte Methode deklariert public procedure Methode; virtual; abstract; end; TAbstraktAbgeleitet = class(TAbstraktBasis); // Abstrakte Klasse, da abstrakte Methode geerbt TKonkretAbgeleitet = class(TAbstraktBasis) // Keine abstrakte Klasse, da Methode implementiert public procedure Methode; override; end; { TKonkretAbgeleitet } procedure TKonkretAbgeleitet.Methode; begin WriteLn('Methode wurde implementiert'); end; { Programmcode } var AbstraktBasis: TAbstraktBasis; AbstraktAbgeleitet: TAbstraktBasis; KonkretAbgeleitet: TKonkretAbgeleitet; begin // Versuche, abstrakte Basisklasse zu instanziieren: AbstraktBasis := TAbstraktBasis.Create; // Versuche, abstrakte abgeleitete Klasse zu instanziieren: AbstraktAbgeleitet := TAbstraktAbgeleitet.Create; // Versuche, konkrete abgeleitete Klasse zu instanziieren: KonkretAbgeleitet := TKonkretAbgeleitet.Create; end. Zitat:
|
AW: Aufruf abstrakter Methode führt zu Fehler
Die einzige Schwachstelle des Compilers ist, das er an dieser Stelle nicht warnt:
Delphi-Quellcode:
Und dieser Programmierfehler wird auch hier die Ursache des Problems sein.
procedure TKonkretAbgeleitet.Methode;
begin inherited Methode; // <- keine Warnung WriteLn('Methode wurde implementiert'); end; |
AW: Aufruf abstrakter Methode führt zu Fehler
Hmmm... Tatsache. Das ist wirklich suboptimal.
|
AW: Aufruf abstrakter Methode führt zu Fehler
Das finde ich nicht. Ansonsten müsste ich ja erst nachschauen, ob die Methode in der Elternklasse implementiert wurde. So juckt mich das nicht, mit dem inherited-Aufruf bin ich auf der sicheren Seite.
|
AW: Aufruf abstrakter Methode führt zu Fehler
Könntet ihr bitte zurück zum Thema kommen anstelle eine Grundsatzdiskussion zu führen?
Zitat:
folgendes kann wirklich der Fehler sein:
Delphi-Quellcode:
aber sowas kann man umgehen indem man schreibt:
procedure TKonkretAbgeleitet.Methode;
begin inherited Methode; // <- Fehlermeldung weil explizit eine abstrakte Methode aufgerufen wird WriteLn('Methode wurde implementiert'); end;
Delphi-Quellcode:
Am besten wäre Quelltext von der Stelle an der, der Fehler auftritt.
procedure TKonkretAbgeleitet.Methode;
begin inherited; WriteLn('Methode wurde implementiert'); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:50 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 by Thomas Breitkreuz