Question

  

Mise à jour: éviscérés la question avec un exemple simple, que vous ne répondez pas   par la réponse initialement acceptée

Compte tenu de la classe suivante, et son ancêtre:

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;

En ce moment TCellPhone a 3 constructeurs visibles:

  • Coupe: Entier
  • Coupe: Integer; Teapot: string
  • Teapot: string = ''

Que dois-je faire pour TCellPhone afin que le constructeur ancêtre (de Teapot: string = '') n'est pas visible, ne laissant que les constructeurs ont déclaré:

  • Coupe: Entier
  • Coupe: Integer; Teapot: string
  

Remarque : En général, le simple fait de ayant un descendant constructeur se cache l'ancêtre:

TCellPhone = class(TComputer)
public
   constructor Create(Cup: Integer); virtual;
end;
     
      
  • Coupe: Entier
  •   
     

Et si vous voulait pour garder le haut   constructeur ancêtre et la   descendant, vous marquerait la   descendant en tant que overload:

TCellPhone = class(TComputer)
public
   constructor Create(Cup: Integer); overload; virtual;
end;
     
      
  • Coupe: Entier
  •   
  • Teapot: string = ''
  •   

Dans le code exemple de cette question, Delphi confond mes mots-clés overload:

TCellPhone = class(TComputer)
public
   constructor Create(Cup: Integer); overload; virtual;
   constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;

de penser que:

  • je veux surcharger mes constructeurs avec ancêtre ,
  • quand je veux vraiment surcharger avec frères et soeurs

Comment cacher le constructeur ancêtre?

Remarque: Il pourrait être impossible de cacher l'ancêtre, non-virtuelle, constructeur en utilisant le langage Delphi tel qu'il est actuellement défini. "Pas possible" est une réponse valable.


Tentative Réponse (échec)

i essayé marquer les constructeurs descendant avec reintroduce (retombant à mon mode de mots-clés en ajoutant au hasard jusqu'à ce que cela fonctionne):

TCellPhone = class(TComputer)
public
   constructor Create(Cup: Integer); reintroduce; overload; virtual;
   constructor Create(Cup: Integer; Teapot: string); reintroduce; overload; virtual;
end;

Mais cela ne fonctionne pas, les trois constructeurs sont encore visibles. : (


Original Question

J'ai un objet qui descend d'une classe qui a les constructeurs ne veulent pas voir:

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)
  

Remarque: Ceci est un exemple hypothétique. Comme dans le monde réel, les objets ancêtres ne peuvent être modifiés sans casser le code existant.

lors de l'utilisation de TiPhone de quelqu'un que je ne veux pas les même pouvoir voir le constructeur de TEniac:

iphone := TiPhone.Create(powerCord);

Pire encore: si elles appellent ce constructeur, ils passent complètement à côté de mon constructeur, et tout fait entre les deux. Il est assez facile d'appeler le constructeur mauvais, tous sont visibles dans l'IDE achèvement de code, et compilera:

TiPhone.Create;

et ils obtiennent un objet complètement invalide.

i pourrait changer TCellPhone de lancer une exception dans ces constructeurs:

TCellPhone.Create(PowerCord: TPowercord)
begin
   raise Exception.Create('Don''t use.');
end;

Mais les développeurs ne se rendent compte qu'ils appellent le mauvais constructeur jusqu'à ce que le client trouve l'erreur un jour et nous amendes bazillions de dollars. En fait, je suis essayer pour trouver partout que j'appelle le mauvais constructeur - mais je ne peux pas comprendre comment faire Delphi me dire

Était-ce utile?

La solution

Il est impossible de faire jamais un constructeur introduit dans un ancêtre inaccessible pour la création d'une classe dérivée en Delphi parce que vous pouvez toujours faire ceci:

type
  TComputerClass = class of TComputer;

var
  CellPhoneClass: TComputerClass = TCellPhone;
  CellPhone : TCellPhone;
begin
  CellPhone := CellPhoneClass.Create('FUBAR') as TCellPhone;
end;

Rien que vous pourriez faire dans le code d'une classe dérivée serait jamais en mesure d'empêcher quiconque d'appeler le constructeur TComputer.Create pour créer une instance de la classe dérivée.

Le mieux que vous pouvez faire est:

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;

Dans ce cas, le code ci-dessus serait au moins appeler TCellPhone.Create(Teapot: string='') au lieu de TComputer.Create(Teapot: string='')

Autres conseils

Si je me souviens bien, puis reintroduce devrait aider virtuel méthodes.

  

reintroduce directive supprime les avertissements du compilateur sur le masquage des méthodes virtuelles déclaré précédemment.   Utilisez reintroduce lorsque vous souhaitez masquer une méthode virtuelle héritée par une nouvelle.

Pour répondre à votre question mise à jour - Je pense que ce n'est pas possbile de cacher un non virtuel constructeur avec une surcharge dans une classe dérivée directement, mais j'ai essayé avec succès le suivant:

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;

Vous ne pouvez pas cacher le constructeur de la classe mère à moins qu'elle a été déclarée virtuelle ou dynamique. Vous pouvez toutefois l'empêcher d'être appelé de la classe des enfants. Considérez votre exemple:

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 sera toujours visible de TCellPhone. Vous pouvez empêcher TComputer.Create d'être appelé par mégarde en déclarant un TCellPhone.Create avec la même signature.

TCellPhone = class(TComputer)
public
   constructor Create(Teapot: string='');
   constructor Create(Cup: Integer); overload; virtual;
   constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;

Alors, tant que vous ne disposez pas d'un appel à inherited dans le corps de TCellPhone.Create(Teapot: string='') vous pouvez empêcher TComputer.Create d'être appelé dans TCellPhone et ses descendants. Ce qui suit:

TCellphone.Create;
TCellphone.Create('MyPhone');

résoudront à la mise en œuvre de TCellPhone.

De plus:

TiPhone = class(TCellPhone)
    constructor Create;
end;

constructor TiPhone.Create;
begin
  inherited;
end;

invoquera TCellPhone.Create et non TComputer.Create.

Au lieu de seulement élever une « Ne pas utiliser » exception dans les constructeurs invalides redéfinies, pensez à les marquer Obsolète dans la classe où ils deviennent invalides. Cela devrait produire des avertissements agréables du compilateur lorsque ces constructeurs invalides sont utilisés erroneosly.

TCellPhone = class(TComputer)
   constructor Create(PowerCord: TPowerCord=nil); deprecated;
   constructor Create(sim: TSimChip; UnlockCode: Integer); //calls inherited Create(nil)

En outre, l'utilisation de remplacement ou rétablir si nécessaire.

Vous voulez réintroduire le constructeur:

TiPhone = class(TCellPhone)
    constructor Create(sim: TSimChip); reintroduce;

Voir TComponent.Create dans le code source Delphi pour un exemple réel de cela.

Je sais que cela est de 5 ans le sujet, mais il peut aider quelqu'un. La seule façon de cacher le constructeur de l'ancêtre est de renommer l'une des deux méthodes de création à autre chose et de supprimer la nécessité de surcharge directive. Il fait un peu bizarre mais c'est la seule façon. Au moins dans les anciennes versions de Delphi. Je ne sais pas, il est désormais possible dans les versions XE xxx.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top