![]() |
Constructor verbergen
Hallo zusammen,
folgende Ausgangssituation: Gegeben sind die folgenden Klassen (abgespeckte Darstellung):
Delphi-Quellcode:
Objekte der Klasse 'TMeinMemo' können direkt Objekte vom Typ 'TMeinMemoObject' erzeugen.
TMeinMemoObject = Class(TObject)
private FValue: String; public Constructor Create(oMemo: TMeinMemo); Property Value: String read FValue; end; TMeinMemo = Class(TMemo) private Function GetMeinMemoObject: TMeinMemoObject; public Property MeinMemoObject : TMeinMemoObject read GetMeinMemoObject; end; Zugriff erfolgt dann über die entsprechende Property, bspw.
Delphi-Quellcode:
So, wie ich nun aber auf das Feld 'Value' zugreifen kann, wäre es genauso möglich, auf den Constructor zuzugreifen:
sMeinString := oMeinMemo.MeinMemoObject.Value;
Delphi-Quellcode:
Und genau das möchte ich verhindern.
oMeinMemo.MeinMemoObject.Create(oMeinMemo);
Im Klartext: ich möchte verhindern, dass ein Objekt der Klasse 'TMeinMemoObject' von außen erzeugt werden kann. Nun dachte ich, dass es genügen würde, den Constructor aus dem Public- einfach in den Private-Bereich zu packen. Leider genügt das nicht, da so ja immer noch der Constructor von der Vorfahrklasse 'TObject' aufrufbar ist. Meine Frage nun: Wie kann ich jeglichen Zugriff auf den Constructor von 'TMeinMemoObject' von außen verhindern, und diesen nur der Klasse 'TMeinMemo' ermöglichen? |
Re: Constructor verbergen
Also ich würde versuchen, den Constructor von TObject zu überschreiben und dann aus public rausnehmen.
Kann sein, dass Du dann eine Warning bekommst, aber auch das kann man bestimmt irgendwie "reparieren". Ausnahmsweise kann man die Warning auch ignorieren. |
Re: Constructor verbergen
Den Constructor kannst Du über strict private sperren.
Diesen kannst Du dann über eine private Function Aufrufen. Diese private Function ist von Klassen aus, die in der selben Unit definiert sind, aufrufbar. Das Prinzip kannst Du Dir angucken, wenn Du mal nach Singleton suchst, da wird auch der Constructor gesperrt. Gruß onlinekater |
Re: Constructor verbergen
Hallo,
Zitat:
Delphi-Quellcode:
Damit erzeugst Du IMHO kein neues Objekt, sondern rufst den Konstruktor eines bestehenden Objekts als normale Methode auf.
sMeinString := oMeinMemo.MeinMemoObject.Value;
Gruß xaromz |
Re: Constructor verbergen
Hallo,
vielen Dank für Eure Tipps. Bezüglich der 'strict private'-Variante habe ich es nun auf zweierlei Art und Weise probiert:
Delphi-Quellcode:
Aufruf dann per
TMeinMemoObject = Class(TObject)
strict private Constructor Create; overload; private FValue: String; Procedure CreateMeinMemoObject(oMemo: TMeinMemo); public Property Value: String read FValue; end; TMeinMemo = Class(TMemo) private Function GetMeinMemoObject: TMeinMemoObject; public Property MeinMemoObject : TMeinMemoObject read GetMeinMemoObject; end;
Delphi-Quellcode:
Diese Variante hat mehrere Compilermeldungen zur Folge:
Procedure TMeinMemo.BaueMemoObject;
var oMemoObject: TMeinMemoObject; Begin oMemoObject := TMeinMemoObject.CreateMeinMemoObject(Self); End; Zitat:
Delphi-Quellcode:
Aufruf dann per
TMeinMemoObject = Class(TObject)
strict private Constructor Create; overload; private FValue: String; protected Constructor Create(oMemo: TMeinMemo); overload; public Property Value: String read FValue; end; TMeinMemo = Class(TMemo) private Function GetMeinMemoObject: TMeinMemoObject; public Property MeinMemoObject : TMeinMemoObject read GetMeinMemoObject; end;
Delphi-Quellcode:
Diese Variante hat nur einen Hinweis zur Folge, der nicht weiter stört
Procedure TMeinMemo.BaueMemoObject;
var oMemoObject: TMeinMemoObject; Begin oMemoObject := TMeinMemoObject.Create(Self); End; Zitat:
Wenn ich nun aber versuche, von außen auf den Constructor zuzugreifen, dann wird mir dieser auch nicht mehr in der CodeVervollständigung angezeigt, aufrufen kann ich ihn aber trotzdem, was dann zu einer Exception führt :cry: Wo liegt der Fehler? Edit: @xaromz Zitat:
Zitat:
|
Re: Constructor verbergen
Hallo,
Zitat:
Delphi-Quellcode:
Damit erzeugst Du IMHO kein neues Objekt, sondern rufst den Konstruktor eines bestehenden Objekts als normale Methode auf.
oMeinMemo.MeinMemoObject.Create(oMeinMemo);
Gruß xaromz |
Re: Constructor verbergen
Ich glaube nicht, dass das "sauber" geht. IMHO ist die beste Lösung (a.k.a das geringste Übel :-)), den "gewollten" Konstruktor privat zu machen sowie den unerwünschten geerbten zu überschreiben und als Implementierung eine Exception zu schmeißen. Damit kriegst du zwar leider keinen Compilerfehler bei unerlaubter Benutzung, aber immerhin einen deutlichen Hinweis zur Laufzeit. :mrgreen:
|
Re: Constructor verbergen
Selbst wenn du den Constructor verbergen kannst bringt dir das überhaupt nichts. Der Constructor ist nichts anderes als eine normale Methode die beim Aufruf als Klassen-Methode speicher anfordert. Wenn du dir aber zum Beispiel mit Application.CreateForm anschaust wirst du sehen das man nicht unbedingt den Constructor als Klassenmethode aufrufen muss um Speicher anzufordern.
Zudem kann man auch einfach immer auf einen Vorgänger casten wo der Constructor sichtbar ist und da den Constructor aufrufen. Der Sinn ist also gleich null von dem was du vor hast. Und wenn du dir mal die Objecte der VCL anschaust wirst du auch nirgends sowas finden obwohl da genau das gleiche mit den Klassengemacht wird wie bei dir (ListView.Items.Add zum Beispiel). |
Re: Constructor verbergen
@xaromz:
Ups, bin schon ganz tüddelig :? Meinte natürlich etwas wie
Delphi-Quellcode:
Procedure TForm1.TestClick(Sender: TObject);
Var oMeinMemoObject: TMeinMemoObject; Begin oMeinMemoObject := TMeinMemoObject.Create(oMeinMemo); End; Zitat:
@SirThornberry Ok, überzeugt - ich lasse es, wie es ist. Prinzipiell ist es ja auch nicht tragisch, da einfach nichts passiert, wenn der Constructor von außen aufgerufen wird. Danke an alle. |
Re: Constructor verbergen
Zitat:
Aber Sicherheit zur Compilezeit kriegst du bei dem Thema mit Delphi AFAICS nicht. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:38 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-2025 by Thomas Breitkreuz