Delphi: Wie Vorfahren Bauer zu verbergen?
-
28-09-2019 - |
Frage
Update: die Frage mit einem einfacheren Beispiel entkernte, die nicht beantwortet wird von der ursprünglich akzeptierten Antwort
In Anbetracht der folgenden Klasse und ihre Vorfahren:
TComputer = class(TObject)
public
constructor Create(Teapot: string='');
end;
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer); overload; virtual;
constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;
Im Moment TCellPhone
hat 3 Konstrukteurs sichtbar:
- Cup: Integer
- Cup: Integer; Teekanne: string
- Teekanne: string = ''
Was tun i TCellPhone
so dass der Vorfahr Konstruktor (Teapot: string = ''
) nicht sichtbar ist, so dass nur die deklarierten Konstruktoren:
- Cup: Integer
- Cup: Integer; Teekanne: string
Hinweis : Normalerweise ist der einfache Akt der mit ein Nachkomme Konstruktor Häuten der Vorfahr:
TCellPhone = class(TComputer) public constructor Create(Cup: Integer); virtual; end;
- Cup: Integer
Und wenn Sie gesucht beide halten die Vorfahr Konstruktor und die Nachkomme, würden Sie die Markierung Abkömmling als
overload
:TCellPhone = class(TComputer) public constructor Create(Cup: Integer); overload; virtual; end;
- Cup: Integer
- Teekanne: string = ''
In diesem Beispiel Code Frage ist Delphi meiner overload
Schlüsselwörter zu verkennen:
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer); overload; virtual;
constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;
denken, dass:
- Ich möchte meine Konstrukteure, um eine Überlastung mit der Vorfahren ,
- wenn ich wirklich will es, um eine Überlastung der Geschwister
Wie blende ich die Vorfahren Konstruktor?
Hinweis: Es könnte unmöglich sein, die Vorfahren, nicht-virtuellen zu verstecken, Konstruktor mit der Sprache Delphi, wie sie derzeit definiert ist. "Nicht möglich" ist eine gültige Antwort.
Versuchte Antwort (nicht)
i versucht, Markieren den Nachkommen Bauer mit reintroduce
(fallen zurück in meinen Modus zufällig das Hinzufügen von Keywords, bis es funktioniert):
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer); reintroduce; overload; virtual;
constructor Create(Cup: Integer; Teapot: string); reintroduce; overload; virtual;
end;
Aber das funktionierte nicht, alle drei Konstrukteure sind noch sichtbar. : (
Original Frage
ich habe ein Objekt, das von einer Klasse, die Konstrukteuren hat nicht wollen, um zu sehen:
TEniac = class(TObject)
constructor Create(PowerCord: TPowerCord=nil); //calls inherited Create
TComputer = class(TEniac) ...
constructor Create(PowerCord: TPowerCord=nil); //calls inherited Create(nil)
TCellPhone = class(TComputer)
constructor Create(sim: TSimChip; UnlockCode: Integer); //calls inherited Create(nil)
TiPhone = class(TCellPhone)
constructor Create(sim: TSimChip); //calls inherited Create(sim, 0)
Hinweis: Dies ist ein hypothetisches Beispiel. Wie in der realen Welt können die Vorfahren Objekte nicht ohne brechen vorhandenen Code geändert werden.
Nun, wenn jemand mit TiPhone
ich will sie nicht einmal in der Lage zu sehen der Konstruktor von TEniac
:
iphone := TiPhone.Create(powerCord);
Schlimmer noch: Wenn sie diesen Konstruktor aufrufen, sie meinen Konstruktor vollständig vermissen, und alles dazwischen getan. Es ist ziemlich einfach die falsche Konstruktor aufzurufen, alle von ihnen in der IDE-Code-Completion sichtbar sind, und kompiliert:
TiPhone.Create;
und sie ein völlig ungültiges Objekt erhalten.
ich kann TCellPhone
ändern, um eine Ausnahme in den Konstrukteuren zu werfen:
TCellPhone.Create(PowerCord: TPowercord)
begin
raise Exception.Create('Don''t use.');
end;
Doch die Entwickler werden nicht merken, dass sie den falschen Konstruktor aufrufen, bis der Kunde den Fehler an einem Tag und Bußgelder uns bazillions Dollar findet. In der Tat, ich bin versuchen finden überall ich den falschen Konstruktor aufrufen - aber ich kann nicht herausfinden, wie ich machen Delphi sagen
Lösung
Es ist unmöglich, jemals einen Erbauer in einem Vorfahren unzugänglich für die Schaffung einer abgeleiteten Klasse in Delphi eingeführt, weil Sie diese immer tun:
type
TComputerClass = class of TComputer;
var
CellPhoneClass: TComputerClass = TCellPhone;
CellPhone : TCellPhone;
begin
CellPhone := CellPhoneClass.Create('FUBAR') as TCellPhone;
end;
Nichts, was Sie in dem Code jeder abgeleiteten Klasse tun konnten, jemals jemanden zu verhindern, wäre in der Lage, die TComputer.Create Konstruktor von Aufrufen für eine Instanz der abgeleiteten Klasse zu schaffen.
Das Beste, was Sie tun können, ist:
TComputer = class(TObject)
public
constructor Create(Teapot: string=''); virtual;
end;
TCellPhone = class(TComputer)
public
constructor Create(Teapot: string=''); overload; override;
constructor Create(Cup: Integer); overload; virtual;
constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;
In diesem Fall wird der Code oben wäre zumindest Aufruf TCellPhone.Create(Teapot: string='')
statt TComputer.Create(Teapot: string='')
Andere Tipps
Wenn ich mich richtig erinnere, dann reintroduce
sollten für virtuellen helfen Methoden.
Die reintroduce Richtlinie unterdrückt Compiler-Warnungen über versteckte virtuelle Methoden zuvor erklärt. Verwenden Sie reintroduce, wenn Sie eine geerbte virtuelle Methode mit einer neuen ausblenden möchten.
Ihre aktualisierte Frage zu beantworten - ich denke, es ist nicht ein nicht-virtuellen Konstruktor mit Überlastung in einem direkt abgeleiteten Klasse zu verstecken ist possbile, aber ich habe versucht die folgenden erfolgreich:
TComputer = class(TObject)
public
constructor Create(Teapot: string='');
end;
TIndermediateComputer = class(TComputer)
protected
// hide the constructor
constructor Create;
end;
TCellPhone = class(TIndermediateComputer)
public
constructor Create(Cup: Integer); overload; virtual;
constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;
Sie können nicht die übergeordnete Klasse Konstruktor verstecken, es sei denn es wurde virtuell oder dynamisch erklärt. Sie können es aber verhindern, dass von der untergeordneten Klasse aufgerufen wird. Betrachten Sie Ihr Beispiel:
TComputer = class(TObject)
public
constructor Create(Teapot: string='');
end;
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer); overload; virtual;
constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;
TComputer.Create
wird von TCellPhone
immer sichtbar sein. Sie können TComputer.Create
von vermeiden, dass durch die Deklaration einer TCellPhone.Create
mit derselben Signatur genannt zu werden.
TCellPhone = class(TComputer)
public
constructor Create(Teapot: string='');
constructor Create(Cup: Integer); overload; virtual;
constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;
Dann solange man Sie inherited
einen Anruf nicht zu TCellPhone.Create(Teapot: string='')
im Körper von TComputer.Create
haben sich von genannt in TCellPhone
und seine Nachkommen verhindern. In dem folgenden:
TCellphone.Create;
TCellphone.Create('MyPhone');
Wird auf TCellPhone Implementierung lösen.
Zusätzlich:
TiPhone = class(TCellPhone)
constructor Create;
end;
constructor TiPhone.Create;
begin
inherited;
end;
Wird TCellPhone.Create
aufrufen und nicht TComputer.Create
.
Statt nur zu heben eine, Ausnahme in den überschriebenen ungültigen Konstrukteuren „Do not verwenden“ betrachten markiert sie deprecated in der Klasse, wo sie ungültig. Das sollte schön Compiler-Warnungen erzeugen, wenn diese ungültigen Konstrukteuren erroneosly verwendet werden.
TCellPhone = class(TComputer)
constructor Create(PowerCord: TPowerCord=nil); deprecated;
constructor Create(sim: TSimChip; UnlockCode: Integer); //calls inherited Create(nil)
Darüber hinaus Verwendung Überschreibung oder reintroduce nach Bedarf.
Sie wollen den Konstruktor wieder einführen:
TiPhone = class(TCellPhone)
constructor Create(sim: TSimChip); reintroduce;
Siehe TComponent.Create
in dem Delphi-Quellcode für ein reales Beispiel dafür.
Ich weiß, dass dies ist 5 Jahre alt Thema, aber immer noch kann es jemanden helfen. Der einzige Weg, die Vorfahren Konstruktor zu verstecken ist eine umbenennen der beide erstellen Methoden, um etwas anderes, und entfernen Sie die Notwendigkeit von Überlastung Richtlinie. Es sieht komisch, aber es ist der einzige Weg. Zumindest in älteren Versionen von Delphi. Ich weiß nicht, ist es möglich, jetzt in der XE-Versionen xxx.