Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Objekterstellung im Konstruktor abbrechen (https://www.delphipraxis.net/54247-objekterstellung-im-konstruktor-abbrechen.html)

Marphy 30. Sep 2005 14:31


Objekterstellung im Konstruktor abbrechen
 
Hallo zusammen,
ich hoffe, dass diese Frage ausnahmsweise mal keine so harte Nuss ist wie meine anderen... :mrgreen:

Also zum Thema:
Ich habe ein Formular mit überschriebenem Create()-Konstruktor, welches dynamisch erstellt wird. Falls eine bestimmte Funktion, die in diesem Konstruktor aufgerufen wird, fehlschlägt (keine Exception, sondern Rückgabewert False), soll die Erstellung des Formulars abgebrochen und es wieder freigegeben werden. Ein Referenz-Parameter im Konstruktor gibt Aufschluss darüber, ob diese bestimmte Funktion fehl schlug oder nicht.

Delphi-Quellcode:
constructor TMyForm.Create(AOwner: TComponent; AMyP: Integer; var ASuccess: Boolean);
begin
  [...]
  if not MyFunc(AMyP) then begin
    Free(); // Oje, das endet böse...
    Exit;
  end;
  [...]
end;
Klar, ich könnte statt Free (was einen bösen Fehler verursacht) eine Exception auslösen und diese beim Create-Aufruf abfangen. Aber ich möchte es einfach eleganter (-> ASuccess)... :???:
Gibt es da einen anderen Lösungsweg?

Ich bin dankbar für jeden Lösungsvorschlag! :-D

Grüße, Marco

P.S.: Damit keiner meckert: :warn: Dieser Beitrag hätte zwar auch ins Forum "VCL / WinForms / Controls" gepasst, da die Frage sich aber eher allgemein auf Objekte als speziell auf "das Formular" bezieht, habe ich sie hier reingestellt.

alzaimar 30. Sep 2005 14:35

Re: Objekterstellung im Konstruktor abbrechen
 
Wieso sind Exceptions nicht elegant?
Delphi-Quellcode:
Try
  anObject := TMyObject.Create;
  anOnject.DoSomeThing;
  anObject.AProperty := FooBar
Except
  Showmessage('Das Objekt konnte nicht erzeugt werden')
End;

Phistev 30. Sep 2005 14:41

Re: Objekterstellung im Konstruktor abbrechen
 
Überschreib TObject.ClassInstance. In der Code-Lib gibt's ein Beispiel (hier) dazu. Einfach die if-Bedingung ändern und evtl. statt raise result:= nil;

@alzaimar: Wenn das Haptprogramm diese Exception dann nicht abfängt...

Sharky 30. Sep 2005 15:02

Re: Objekterstellung im Konstruktor abbrechen
 
Zitat:

Zitat von Phistev
... @alzaimar: Wenn das Haptprogramm diese Exception dann nicht abfängt...

... Hat es genau das selbe Problem als wenn die Variable ASuccess nicht ausgewertet wird ;-)

Die Frage die ich mir stelle: Ist es sinnvoll das mit der Variable zu machen? Immerhin ist es ja fast normal das man mit Try-Except arbeitet.

Oder noch besser gefragt: Was ist der Grund das ich ein Objekt nicht erzeugen kann? Dies sollte ja ein böser Fehler sein und dann finde ich es besser dies mit den Standardmöglichkeiten zu machen.

DerDan 30. Sep 2005 15:23

Re: Objekterstellung im Konstruktor abbrechen
 
oder du machst eine

Class Function CheckAndCreate;

Die dir die Instanz zurückliefert oder auch NIL falls deine Prüfung entsprechendes sagt.

Delphi-Quellcode:
Class Function TMyObj.CheckAndCreate : TMyObj;
begin
  result = TMyObj.Create;
  if not result.Check then
  begin
    freeandnil (result);
  end;
end;
mfg

Der Dan

alzaimar 30. Sep 2005 15:25

Re: Objekterstellung im Konstruktor abbrechen
 
Hi PHistev,
Dein Einwand ist sinnlos. Wer die Exception nicht abfängt wird auch den Flag 'Success' nicht abfragen.

Aber wenn die Exception nicht abgefangen wird, passiert zumindest eins nicht: "Nil Pointer exception"

Deine Variante:
Delphi-Quellcode:
  ...
  MyObject := TMyObject.Create (Success);
  MyObject.DoSomething; // <-- Phatoomp, wenn Success = False,
  ...
Meine Variante:
Delphi-Quellcode:
  ...
  MyObject := TMyObject.Create;
  MyObject.DoSomething; // <-- Wird erst gar nicht ausgeführt, und der Anwender sieht, wie gut der Entwickler ist!
  ...
Frage: Was ist besser? Was ist sicherer? Was führt vielleicht mal zu unangenehmen Effekten?

@DerDan: Noch eine Möglichkeit. Viele Wege führen nach Rom. Aber Dein Weg ist wenigstens gepflastert :zwinker: Hat aber einen Nachteil: Es wird ein illegales Objekt erzeugt. Es kann ja sein, das das Objekt einfach nicht erzeugt werden _kann_ (oder nur mit Schwierigkeiten).

Ich bleib dabei: Mit Exception ist's am einfachsten. Vielleicht sogar mit der ClassFunction von DerDan.

DerDan 30. Sep 2005 15:33

Re: Objekterstellung im Konstruktor abbrechen
 
Zitat:

Zitat von alzaimar
@DerDan: Noch eine Möglichkeit. Viele Wege führen nach Rom. Aber Dein Weg ist wenigstens gepflastert :zwinker: Hat aber einen Nachteil: Es wird ein illegales Objekt erzeugt. Es kann ja sein, das das Objekt einfach nicht erzeugt werden _kann_ (oder nur mit Schwierigkeiten).

Ich bleib dabei: Mit Exception ist's am einfachsten. Vielleicht sogar mit der ClassFunction von DerDan.

Bei einem einfachen Create muss ja noch nichts von dem Aufgerufen werden, was das anlegen verhindert.
Das kann man ja in die Function Check reinlegen.
Von da her seh ich keine Situation bei der man nicht mal erst ein Object anlegen können sollte.

Wird übrigens bei allen anderen Varianten hier in den obigen beispielen auch gemacht

Marphy 1. Okt 2005 16:25

Re: Objekterstellung im Konstruktor abbrechen
 
Hallo zusammen,
danke erstmal für die zahlreichen Antworten... :-D

Nun, zum besseren Verständnis der Situation:
Ich will direkt im Create-Konstruktor des Formulars Daten in selbiges laden. Da dies aber scheitern kann, soll bei einem Fehler die Erstellung der Form abgebrochen werden. Die Funktion zum Laden der Daten verursacht bei Fehlern (normalerweise) keine Exception, sondern gibt den Erfolg über Result zurück.

Die beste Lösung meines Problems ist wohl die Kombination von "Exception" und ASuccess.

Delphi-Quellcode:
constructor TMyForm.Create(AOwner: TComponent; AMyP: Integer; var ASuccess: Boolean);
begin
  ASuccess := False;
  [...]
  if not MyFunc(AMyP) then
    Abort(); // Aha...
  [...]
  ASuccess := True;
end;

[...]
  try
    TMyForm.Create(Self, 123, Success);
  except
    if not ASuccess then
      // Funktion gescheitert
  end;
[...]
Tjaja, diese Abort-Prozedur hat mir gefehlt... :stupid:

Richtig Sinn macht ASuccess zugegebenermaßen eigentlich erst, wenn es über eine Enumeration Aufschluss über den Erfolg bzw. Nichterfolg der Formularerstellung gibt, was sich aber problemlos erweitern lässt.

Viele Grüße,
Marco

alzaimar 1. Okt 2005 18:42

Re: Objekterstellung im Konstruktor abbrechen
 
Ich würde mich mal näher mit Exceptions, bzw. der Programmflusskontrolle beschäftigen. Dann kannst Du ziemlich elegant deine 'Enumeration' vergessen und den Grund des Scheiterns komplett über Exceptions abbilden. Du definierst Dir einfach verschiedene Exceptionklassen, die Du individuell abfangen kannst (steht alles in der OH)
Delphi-Quellcode:
Type
  EWrongParameter = Class (Exception);
  EInvalidUsage = Class (Exception);
...
Constructor TMyObject.Create (aParameter : TSomeType);
Begin
  Inherited;
  If UsageInvalid Then
    Raise EInvalidUsage.Create ('Some Text');
  If Not CheckParameter (aParameter) Then
    Raise EWrongParameter.CreateFmt('Wrong parameter type %s',[aParameter]);
  ...
End;
...

Begin
  Try
    oMyObject := TMyObject.Create;
    oMyObject.CanCallMethods;
  Except
    On E:EInvalidUsage Do
      HandleError;
    On E:EWrongParameter Do
      HandleAnotherError;
   // Alle anderen Fehler (Speicher etc.) werden nicht abgefangen und werden weitergeleitet!
    End;
...
End;
So hast Du eine strikte Trennung im Programm. Der normale Programmfluss ist klar sichtbar und die Fehlerbehandlung ist abgegrenzt.

Marphy 1. Okt 2005 19:30

Re: Objekterstellung im Konstruktor abbrechen
 
Hallo Alzaimar,

Zitat:

Zitat von alzaimar
Ich würde mich mal näher mit Exceptions, bzw. der Programmflusskontrolle beschäftigen. Dann kannst Du ziemlich elegant deine 'Enumeration' vergessen und den Grund des Scheiterns komplett über Exceptions abbilden. Du definierst Dir einfach verschiedene Exceptionklassen, die Du individuell abfangen kannst (steht alles in der OH)
[...]
So hast Du eine strikte Trennung im Programm. Der normale Programmfluss ist klar sichtbar und die Fehlerbehandlung ist abgegrenzt.

Danke für den Hinweis... Du hast schon Recht, wenn man die Möglichkeiten der Exceptions geschickt nutzt, kann das einige Vorteile bringen. Ich werde mich mal eingehender damit beschäftigen, danke nochmal. :)

Gruß, Marco


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:02 Uhr.
Seite 1 von 3  1 23      

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