Autor |
Beitrag |
MitschL
      
Beiträge: 211
Win 98 SE, Win 2000
D5 Pers, D6 Pers und D7 Pro
|
Verfasst: 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.
Delphi-Quelltext 1: 2: 3: 4: 5:
| type FileClass = class( TObject ) 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:
Delphi-Quelltext 1: 2: 3:
| myInstance := FileClass.Create( path ); if myInstance = nil then |
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 Tino: Topic aus Sonstiges verschoben am Do 13.01.2005 um 10:01
|
|
Stefan.Buchholtz
      
Beiträge: 612
WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
|
Verfasst: 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
      
Beiträge: 33
|
Verfasst: Mo 10.01.05 17:07
oder mach's doch mit einer klassenfunktion die dir eine instanz zurück gibt wenn die datei existiert:
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 
      
Beiträge: 211
Win 98 SE, Win 2000
D5 Pers, D6 Pers und D7 Pro
|
Verfasst: 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.
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.
gegrüßt!
MitschL
|
|
Stefan.Buchholtz
      
Beiträge: 612
WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
|
Verfasst: 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.
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
|
Verfasst: 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
      
Beiträge: 612
WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
|
Verfasst: 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 
      
Beiträge: 211
Win 98 SE, Win 2000
D5 Pers, D6 Pers und D7 Pro
|
Verfasst: 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
      
Beiträge: 612
WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
|
Verfasst: 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
|
Verfasst: 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
      
Beiträge: 612
WIN 2000, WIN XP, Mac OS X
D7 Enterprise, XCode, Eclipse, Ruby On Rails
|
Verfasst: 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:
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
|
|
|