Autor Beitrag
MitschL
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 211

Win 98 SE, Win 2000
D5 Pers, D6 Pers und D7 Pro
BeitragVerfasst: Mo 10.01.05 16:21 
Ich grüße mal ganz brav und möchte aufgrund von geringer Sicht wegen Holz vor Augen gleich zum Thema kommen.

Ich möchte beim Instanziieren eines Objektes diese Instanz nicht anlegen, wenn ein Fehler vorliegt.
Ich habe mal - um dem Detail die Ehre zu geben - eine Klasse, die mit einer wichtigen Datei arbeitet, so konstruieren lassen.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
 type FileClass = class( TObject )
  // blablabla
  public

    constructor Create( path: String ); reintroduce;

// blablabla
end;
Ich möchte meine Fehlerbehandlung nun nach außen heben, indem ich die Instanz nur anlegen lasse, wenn die Datei existiert.
Damit ich dann sowas machen kann:
ausblenden Delphi-Quelltext
1:
2:
3:
 myInstance := FileClass.Create( path );
if myInstance = nil then
// Fehler! Jaha! Keine Arbeit! Feierabend!

Ich kann das Objekt ja eigentlich nicht im Create wieder freigeben, also muß ich das Instanziieren des selben verhindern, oder?

Wenn einer eine Antwort weis, wäre ich geradezu verzückt, so hören zu dürfen

gegrüßt!
MitschL


Moderiert von user profile iconTino: Topic aus Sonstiges verschoben am Do 13.01.2005 um 10:01
Stefan.Buchholtz
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Mo 10.01.05 16:58 
Das lässt sich einfach erreichen, wenn du den Konstruktor beim Auftreten der Fehlerbedingung einfach eine Exception werfen lässt. Dann wird sofort der Destruktor aufgerufen und das Objekt wieder freigegeben.
Du solltest die Exception natürlich in dem Code, der das Objekt erzeugt, behandeln, wenn du nicht eine häßliche Fehlermeldung haben willst. Ausserdem sollte der Destruktor mit einem unvollständig initialisierten Objekt klarkommen - der Konstruktor wurde ja noch gar nicht komplett ausgeführt.

Stefan
bttb930
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 33



BeitragVerfasst: Mo 10.01.05 17:07 
oder mach's doch mit einer klassenfunktion die dir eine instanz zurück gibt wenn die datei existiert:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
  TTest = class
  public
    constructor Create(aPath: string);
    class function test(aPath: string):TTest;
  end;

class function TTest.test(aPath: string):TTest;
begin
  if FileExists(aPath) then
    Result := TTest.Create(aPath)
  else
    Result := nil;
end;

...
  Test := TTest.Test('c:\test.txt');
MitschL Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 211

Win 98 SE, Win 2000
D5 Pers, D6 Pers und D7 Pro
BeitragVerfasst: Mo 10.01.05 17:42 
Ich danke euch schonmal,

@ Stefan.Buchholtz: Exception-Handling kam mir auch in den Sinn, ist in meinem Code aber seltener vertreten. Man kann das als ganz persönlichen Splin abtun.

Stefan.Buchholtz hat folgendes geschrieben:
Ausserdem sollte der Destruktor mit einem unvollständig initialisierten Objekt klarkommen - der Konstruktor wurde ja noch gar nicht komplett ausgeführt.

Dann muß man doch an genau den Destruktor rankommen können. :twisted:


bttb930 hat folgendes geschrieben:
oder mach's doch mit einer klassenfunktion die dir eine instanz zurück gibt wenn die datei existiert:

Dann habe ich eine globale Variable. Hm. Gefällt mir nicht sonderlich. Schade, daß es keine statischen Variablen in Delphi gibt, dann wäre das mit einer Klassenmethode einfacher.

Mich deucht, es wird das Exception-Handling. :?

oder, was mir mehr zusagt. 8)

gegrüßt!
MitschL
Stefan.Buchholtz
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Mo 10.01.05 17:57 
MitschL hat folgendes geschrieben:

bttb930 hat folgendes geschrieben:
oder mach's doch mit einer klassenfunktion die dir eine instanz zurück gibt wenn die datei existiert:

Dann habe ich eine globale Variable. Hm. Gefällt mir nicht sonderlich. Schade, daß es keine statischen Variablen in Delphi gibt, dann wäre das mit einer Klassenmethode einfacher.

Mich deucht, es wird das Exception-Handling. :?

oder, was mir mehr zusagt. 8)

gegrüßt!
MitschL


Mit der Klassenfunktion brauchst du keine globale Variable - du kannst die aufrufen, wie du den Konstruktor aufrufen würdest.
Ob man diese Lösung oder eine Exception benutzt, ist dann Geschmackssache... :)
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 10.01.05 18:17 
Die Delphi Hilfe sagt zu TObject.Create:
Zitat:

Note: If an exception escapes from a constructor, the object’s destructor is called to clean up the failed instance.

Sprich, man brauch selber keine Exception zu werfen, der Destruktor wird automatisch aufgerufen, wenn eine Exception auftritt.
Stefan.Buchholtz
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Mo 10.01.05 18:39 
Luckie hat folgendes geschrieben:
Die Delphi Hilfe sagt zu TObject.Create:
Zitat:

Note: If an exception escapes from a constructor, the object’s destructor is called to clean up the failed instance.

Sprich, man brauch selber keine Exception zu werfen, der Destruktor wird automatisch aufgerufen, wenn eine Exception auftritt.


Genau dieses Verhalten nutzt mein Vorschlag ja aus - die ursprüngliche Frage ging ja darum, wie man die Erzeugung des Objekts verhindern kann, wenn im Konstruktor ein Fehler auftritt.

Stefan
MitschL Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 211

Win 98 SE, Win 2000
D5 Pers, D6 Pers und D7 Pro
BeitragVerfasst: Mo 10.01.05 18:59 
Ich wieder,

Stefan.Buchholtz hat folgendes geschrieben:
Mit der Klassenfunktion brauchst du keine globale Variable - du kannst die aufrufen, wie du den Konstruktor aufrufen würdest.
Ob man diese Lösung oder eine Exception benutzt, ist dann Geschmackssache... :)


Ich hab Bohnen auf die Glühsen. War ja nur der Aufruf unter der Klassendeklaration von bttb930.
Vorsichtshalber sollte ich doch aber den Konstruktor in den private-Bereich verziehen und durch reintroduce, das Vererbende verhindern, oder?

Ich tendiere zu dieser Methode und danke brav.

gegrüßt!
MitschL
Stefan.Buchholtz
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Mo 10.01.05 19:04 
MitschL hat folgendes geschrieben:
Ich wieder,
Vorsichtshalber sollte ich doch aber den Konstruktor in den private-Bereich verziehen und durch reintroduce, das Vererbende verhindern, oder?

Ich tendiere zu dieser Methode und danke brav.

gegrüßt!
MitschL


Der Konstruktor kann dann private sein - du würdest die Klasse dann ja nur über die Klassenfunktion erzeugen.

Stefan
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 10.01.05 19:24 
Stefan.Buchholtz hat folgendes geschrieben:

Genau dieses Verhalten nutzt mein Vorschlag ja aus - die ursprüngliche Frage ging ja darum, wie man die Erzeugung des Objekts verhindern kann, wenn im Konstruktor ein Fehler auftritt.

Brauchst du ja gar nicht verhindern, da das Objekt ja automatisch wieder zerstört wird, wenn eine Exception im Konstruktor auftriit.
Stefan.Buchholtz
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 612

WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
BeitragVerfasst: Mo 10.01.05 19:36 
Luckie hat folgendes geschrieben:

Brauchst du ja gar nicht verhindern, da das Objekt ja automatisch wieder zerstört wird, wenn eine Exception im Konstruktor auftriit.


Das ist klar. Es ging eben darum, die Exception selbst zu werfen, wenn der Konstruktor selbst ein Problem feststellt, also z.B. sowas:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
constructor TTest.Create(fileName: string);
begin
  if not FileExists(fileName) then
  begin
    raise ETestException.CreateFmt('Datei %s nicht gefunden!', [fileName]);
  end;
  ...
end;


Stefan