Hallo,
ich möchte ein Objekt mit Parametern initiieren und der Konstruktor soll die Parameter überprüfen. Bei fehlerhaften Parametern soll die Initiierung abgebrochen werden.
Wie kann ich das anstellen?
Bis dann,
Jan
Hallo,
ich möchte ein Objekt mit Parametern initiieren und der Konstruktor soll die Parameter überprüfen. Bei fehlerhaften Parametern soll die Initiierung abgebrochen werden.
Wie kann ich das anstellen?
Bis dann,
Jan
Hallo Jan,
ich möchte ein Objekt mit Parametern initiieren und der
Konstruktor soll die Parameter überprüfen. Bei fehlerhaften
Parametern soll die Initiierung abgebrochen werden.
wenn Dein Konstruktor die Parameter überprüfen kann, dann kannst Du auch eine äquivalente Funktion, die nicht an Deine Klasse gebunden ist und den Check auf genau dieselbe Art und Weise durchführt, schreiben, oder? Also für mich kommt als „richtige“ Reihenfolge (auch im Sinne eines guten Programmierstils) irgendwie nur die in Frage: Erst Parameter überprüfen; wenn Überprüfung OK liefert: Objekt erzeugen; wenn nicht OK: Objekt nicht erzeugen.
Mit freundlichem Gruß
Martin
Hallo Jan,
ich möchte ein Objekt mit Parametern initiieren und der
Konstruktor soll die Parameter überprüfen. Bei fehlerhaften
Parametern soll die Initiierung abgebrochen werden.wenn Dein Konstruktor die Parameter überprüfen kann, dann
kannst Du auch eine äquivalente Funktion, die nicht an Deine
Klasse gebunden ist und den Check auf genau dieselbe Art und
Weise durchführt, schreiben, oder? Also für mich kommt als
„richtige“ Reihenfolge (auch im Sinne eines guten
Programmierstils) irgendwie nur die in Frage: Erst Parameter
überprüfen; wenn Überprüfung OK liefert: Objekt erzeugen; wenn
nicht OK: Objekt nicht erzeugen.
Hallo Martin,
das ginge. Dann wäre die Funktion aber nicht mehr gekapselt. Ich denke, dass es wesentlich eleganter wäre, wenn der Konstruktor sich selbst überprüft (auch im Sinne der Wiederverwendbarkeit).
Bis dann,
Jan
Hallo,
ich möchte ein Objekt mit Parametern initiieren und der
Konstruktor soll die Parameter überprüfen. Bei fehlerhaften
Parametern soll die Initiierung abgebrochen werden.Wie kann ich das anstellen?
Folgende Routine funktioniert (auch mit MemoryCheck)
Trotzdem würde ich genauso wie Martin diesen Constructor nicht verwenden. Der Name ist immerhin Create und nicht CreateIfOK
Servus,
Manfred
constructor create(Var isOK:Boolean);
begin
isOK:= ???
If not isOK then Begin Destroy; Exit; End;
inherited Create;
.
.
.
end;
Bis dann,
Jan
Hi Jan!
Dann wäre die Funktion aber nicht mehr gekapselt.
Wenn Du die objektorientierte Programmierung so betreibst, wie sich die OOP-Erfinder das gedacht haben, ist die Überprüfungsfunktion gekapselt, bloß in einer anderen Klasse!
Deine „Parameter“, die Du im Konstruktor überprüfen lassen willst, müssen (in einem sehr allgemeinen Sinn) so etwas wie einen „Übergang“ von einer Klasse zu einer anderen darstellen. Die erste ist wahrscheinlich eine größere Klasse, die Daten bereitstellt, die von irgendwoher kommen (das kann eine andere, noch „tiefere“ Klasse sein oder die Peripherie, also z. B. die Maus). Die zweite ist eine weiterverarbeitende „Folgeklasse“, die z. B. die Aufgabe hat, die Daten auf dem Bildschirm darzustellen. Die „Parameter“ gehören nun gewissermaßen zu beiden Klassen (was ganz und gar nichts ungewöhnliches ist). In einem solchen Fall sollte die Parameterüberprüfung dann noch in der Klasse stattfinden, die die Daten bereitstellt, nicht in der anzeigenden Folgeklasse.
So ein Konstruktor hat nur genau zwei Aufgaben zu erfüllen: 1. Die Allozierung von Speicher für eine Instanz der betreffenden Klasse, und 2. die Herstellung eines „sinnvollen Anfangszustands“ für das Objekt, indem die Felder auf passende Werte gesetzt werden (wozu gegebenenfalls auch die Erzeugung von Unterobjekten gehört, die sich im Besitz der Klasse befinden). Für Parameterüberprüfungen ist er nicht gedacht (er kann z. B. auch keinen boolschen Wert zurückliefern, der angibt, ob die Klasse nun erzeugt wurde oder nicht).
Von der Parameterüberprüfung im Konstruktor rate ich Dir nochmals nachdrücklich ab.
Mit freundlichem Gruß
Martin
Probier’s mit einer Klassenfunktion, welche die Parameter prüft und ggf. dann create aufruft und die erzeugte Instanz (oder NIL) zurückgibt.
Jo
[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]
Probier’s mit einer Klassenfunktion, welche die Parameter
prüft und ggf. dann create aufruft und die erzeugte Instanz
(oder NIL) zurückgibt.
Hi Jan ,
probier doch erst mal im Constructor die Zeile „Result:=nil“ einzufügen und dann weißt Du welches Problem wir haben.
Manfred
Hallo Martin,
dein Vorschlag, die Instanz nur aus einer anderen, übergeordneten Klasse heraus initiieren zu dürfen, hört sich sehr elegant an (und darauf kommt es ja an).
Dann muss man aber verhindern, dass irgend jemand anderes den Konstruktor aufrufen darf.
Ich habe erfolglos probiert, den Konstruktor einfach unter „private“ einzufügen. Das führte jedoch dazu, dass danach der ererbte Konstruktor ausführbar war.
Wie kann ich lenken, welche Klasse den Konstruktor aufrufen darf?
Vielen Dank,
Jan
Hallo Manfred,
ich weiß nicht, was du meinst. Abgesehen davon: Der Aufruf des Konstruktors reserviert intern ja schon den Speicher und erzeugt die Instanz. Durch das „vernichten“ der Referenz auf die Insanz verlierst du lediglich die Möglichkeit, diese später freigeben zu können. Den Konstruktor darf man also erst aufrufen, wenn man auch wirklich eine instanz erzeugen möchte.
Mein Vorschlag war, den Konstruktor in einer Klassenfunktion aufzurufen, WENN die Parameter ok sind. Die Klassenfunktion gibt dann die Referenz auf die Instanz zurück (so wie das normalerweise auch die Konstruktoren machen). Sie gibt dann NIL zurück, wenn der Konstruktor garnicht erst aufgerufen wurde.
Jochen
[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]
Probier’s mit einer Klassenfunktion, welche die Parameter
prüft und ggf. dann create aufruft und die erzeugte Instanz
(oder NIL) zurückgibt.Hi Jan ,
probier doch erst mal im Constructor die Zeile „Result:=nil“
einzufügen und dann weißt Du welches Problem wir haben.Manfred
Hallo Manfred,
ich weiß nicht, was du meinst. Abgesehen davon: Der Aufruf des
Konstruktors reserviert intern ja schon den Speicher und
erzeugt die Instanz. Durch das „vernichten“ der Referenz auf
die Insanz verlierst du lediglich die Möglichkeit, diese
später freigeben zu können. Den Konstruktor darf man also erst
aufrufen, wenn man auch wirklich eine instanz erzeugen möchte.Mein Vorschlag war, den Konstruktor in einer Klassenfunktion
aufzurufen, WENN die Parameter ok sind. Die Klassenfunktion
gibt dann die Referenz auf die Instanz zurück (so wie das
normalerweise auch die Konstruktoren machen). Sie gibt dann
NIL zurück, wenn der Konstruktor garnicht erst aufgerufen
wurde.
Hallo,
mir scheint, dass auf diese Weise eine ordentliche Initialisierung sicher gestellt werden kann. Eine unsichere Initialisierung über den direkten Aufruf des Konstruktors wir aber nicht verhindert wie mir scheint.
Was meint ihr dazu?
Bis dann,
Jan
Hallo Jan,
Dann muss man aber verhindern, dass irgend jemand anderes den
Konstruktor aufrufen darf.
das Grundprinzip „Kapselung“ der OOP bezieht sich nur auf die „Daten“ (= Gesamtheit der „Felder“) eines Objekts. Der „optimale Zustand“ im Sinne der OOP ist dann erreicht, wenn alle Felder eines Objekts gegen einen „unkontrollierten Zugriff“ von außen geschützt sind (übertragen auf Object Pascal: …wenn alle Felder einer Klasse im PRIVATE- oder PROTECTED-Bereich liegen). Jegliche Manipulationen am Objekt dürfen also außschließlich über einen ausgewählten Satz an „öffentlichen“ Methoden möglich sein (das Objekt muß stets „merken“ können, wenn es geändert wird).
Grundsätzlich nicht beschränken kannst Du dagegen, welche Klasse eine andere Klasse erzeugt. Eine solche Möglichkeit gibt es einfach deshalb nicht, weil es nicht vorkommen kann, daß eine Klasse X eine andere Klasse Y „versehentlich“ kreatiert (kann es passieren, daß Du innerhalb einer zu einer Klasse „TVerkehrsampel“ gehörenden Prozedur versehentlich „BlauesLicht := TVerkehrsAmpelLicht.Create“ schreibst?) Die OOP gibt dem Anwender nur die Möglichkeit (und die Empfehlung), die Daten eines Objekts nach außen „abzuriegeln“ und „Schnittstellen“ zur Außenwelt mit genau definiertem Verhalten zu schaffen. Um die „Verknüpfungen“ zwischen den Klassen kümmert sie sich dagegen keinen Deut.
Also:
Ich habe erfolglos probiert, den Konstruktor einfach unter
„private“ einzufügen. Das führte jedoch dazu, dass danach der
ererbte Konstruktor ausführbar war.
Konstuktoren und Destruktoren immer „PUBLIC“.
Wie kann ich lenken, welche Klasse den Konstruktor aufrufen darf?
Garnicht.
Mit freundlichem Gruß
Martin
Hallo,
mir scheint, dass auf diese Weise eine ordentliche
Initialisierung sicher gestellt werden kann. Eine unsichere
Initialisierung über den direkten Aufruf des Konstruktors wir
aber nicht verhindert wie mir scheint.
Was meint ihr dazu?
Bis dann,
Jan
Auch Hallo !
Das ist im Prinzip richtig. Da ist die Frage: Kann der Konstruktor denn UNBEABSICHTIGTERWEISE denn im Programm direkt aufgerufen werden (UND dann mit falschen Parametern) ?
Weiterhin kann man den originären Konstruktor verbergen, indem die neue Funktion den selben Namen erhält (also „create“ und als public deklariert wird). Der Compiler warnt dann auch ordnungsgemäß, aber das will man ja so.
Also ?
Jochen
Hallo Martin,
jetzt habe ich doch erst mal etwas nachdenken müssen. Ich halte es für sehr wichtig, die Filosofie (schreibt man das jetzt so?) der OOP ordentlich einzuhalten.
Ich glaube, ich habe verstanden wies abläuft.
Vielen Dank für deine Hilfe,
ich werde sicher noch oft auf wer-weiss-was zurückkommen.
Bis dann,
Jan