7
votes

Delphi: Quand réintroduisez-vous de cacher les ancêtres et quand cela leur montre-t-il?

Aujourd'hui strike> Récemment sur Stackoverflow i appris que:


7 commentaires

@Ian: Vous demandez vraiment beaucoup de questions aujourd'hui! Agréable!


Voulez-vous vraiment dire que vous pouvez compiler Run obj: = tcellphone.create ('foo') ? Je trouve cela surprenant.


J'ai certainement exécuté un exemple complet en utilisant ces définitions. Heureusement, nous avons déjà la réponse ci-dessous.


@Andreas Rejbrand Je sais, je sais. Mais quand je pose des questions "grandes images", je n'ai pas de réponses détaillées. Donc, je dois poser des questions de teey-minuscules et les trouver ensemble. Je suis aussi à ma fin d'essayer d'essayer de donner un sens à tout cela. Même Rob, deux commentaires ci-dessus, ne peuvent pas croire au code que j'ai présenté des œuvres. Au moins je ne suis pas seul dans ma confusion.


@Rob Kennedy Je peux modifier la question avec une capture d'écran, si vous aimez?


Non, Ian, je voulais juste m'assurer que j'étais interprétant correctement ce que vous avez dit parce que le code ici n'est pas identique à l'exemple [@ Muhammad] [1] - la méthode de base n'est pas virtuelle, et il existe plusieurs méthodes dans le descendant , qui n'utilise aucun réintroduire .


@ROB Oui, il semble que des différences très mineures modifient considérablement la réponse et la compréhension de ce sujet: /


4 Réponses :


7
votes

Vous n'utilisez pas réintroduire pour masquer une méthode d'une classe d'ancêtre. Vous faites cela simplement en déclarant une méthode avec le même nom que celui de la classe ancêtre sans le remplacer ni la surcharger. Vous utilisez réintroduire pour supprimer le avertissement que Delphi augmente lorsque la méthode de la classe ancêtre (celle étant cachée) est virtuelle.

Si la méthode du descendant remplace l'ancêtre, alors il ne se cache pas. Les appels vers la méthode de l'ancêtre sont acheminés vers le descendant.

Si la méthode du descendant surcharge l'ancêtre, alors il ne se cache pas non plus. Les deux sont disponibles pour appeler.


4 commentaires

Il y a le cas particulier lorsqu'il surcharge une méthode virtuelle. Vous pouvez utiliser le réintroduct combiné; surcharge; . Cela semble ne pas s'intégrer bien avec votre explication, comme une surcharge nue produit l'avertissement.


WRT ce que Muhammad a dit, pouvez-vous élargir votre réponse, Rob, expliquer ce qui se passe dans ce cas (le cas où l'ajout réintroduite est utilisé pour masquer une méthode d'un ancêtre classer)?


J'ai bien peur que je ne puisse pas, @ian. Cela vous obligera à expérimenter et je n'ai pas de compilateur Delphi disponible pour le faire. Quelqu'un d'autre devra énumérer toutes les différentes manières que ces directives peuvent être utilisées ensemble et les effets des effets (ou n'ont pas).


Je vais élargir la question où réintroduite cache une méthode d'ancêtre non virtuel (ou peut-être que c'est un effet secondaire de supprimer un avertissement)



1
votes

Vous ne pouvez pas remplacer une méthode qui n'est pas virtuelle, alors vous ne cachez rien. C'est pourquoi il n'y a pas d'avertissement.

EDIT: Je retirerais mon assertion "Vous ne cachez rien" . Je pense que je ne comprends pas tout à fait la signification de se cacher ici. J'ai demandé à un Questaton sur ceci.

mise à jour:
basé sur le Réponse J'ai eu, j'aimerais réexécuter ma réponse: puisque tcomputer.Constructor n'est pas déclaré Virtual, vous avez déjà caché cette méthode des classes descendantes. Donc, tcellphone Constructeurs ne peut pas masquer ce qui n'a pas été visible du tout, sans aucun avertissement de compilateur.


7 commentaires

C'est la bonne réponse. Plus précisément, le constructeur de TComputer doit être virtuel pour déclencher les avertissements.


Mais Sertac, ce que dise Ian dit que tcomputer.create n'est pas masqué dans ce cas. Il peut appeler tcellphone.create ('foo') , et le code compile et exécute, créant un objet tcellphone . Il a proposé de fournir un coup d'écran pour le prouver.


@ROB - J'ai demandé à un question sur quel compilateur signifiait avec cache . Il ne s'agit pas de ne pas pouvoir appeler du tout, cela signifie que vous ne pourrez pas remplacer TComputer.Constructor dans les descendants de tcellphone . S'il vous plaît voir La réponse de Ken et le commentaire de Barry.


@Sertas Akyuz Vous ne pouvez pas remplacer TComputer.Constructor car ce n'est pas virtuel - pas parce que c'est "caché".


@Ian - il est caché parce que ce n'est pas virtuel. Ou de reformuler: si ce n'est pas virtuel, il est caché depuis que vous ne pouvez pas le remplacer. Eh bien, au moins c'est comme ça que je comprends ..


@Sertatac mais ce n'est pas caché et ce n'est pas virtuel.


@Ian - tout va vraiment à ce que caché signifie. Si cela signifie "Vous ne pourrez pas accéder à la constructeur de TComputer" Vous êtes absolument correct. Si cela signifie cependant, "Vous ne pourrez pas remplacer le constructeur de TComputer des descendants de TCellphone" Je devrais avoir raison. Si cela signifie encore autre chose, .. qui sait!



0
votes

Je voulais mettre cela comme commentaire à la réponse de Rob Kennedy, mais depuis que je ne peux pas, ici je vais ..

Tout le moment où il n'y a aucun avertissement sur la masquage des constructeurs ancêtres. P> blockQuote>

simplement parce que vous ne le faites pas. P>

Si je cache l'ancêtre, pourquoi n'y a-t-il pas d'avertissement? Je n'ai pas de réintroduire. P> BlockQuote>

Encore une fois, simplement parce que vous ne cachez rien. P>

Vous avez vu la preuve que vous n'avez pas caché quoi que ce soit. Ce sont les 3 constructeurs disponibles que vous avez inspectés est la preuve. P>

Pourquoi réintroduire peut-il être utilisé pour cacher l'ancêtre? p> BlockQuote>

Comme Rob mentionné, Reintroduire est simplement supprimer le compilateur indice / avertissement. Il n'y a pas de véritable technicité derrière ce mot. Ainsi, vous ne cachez rien avec réintrocegez. P>

Je voudrais mettre ma pensée sur la façon de se cacher, mais je suis d'accord avec Sertac, je dois d'abord savoir quelle est votre définition de la dissimulation dans ce cas. P>

EDIT: Je viens de lire les messages que vous avez mentionnés, je pense que vous avez mal compris les concepts. Voici ma courte explication. P>

réintroduct est utilisé pour masquer les constructeurs d'ancêtres P> BlockQuote>

La réponse de ce poste n'indique pas cela. Celui qui cache vraiment le constructeur de l'ancêtre est le nouveau constructeur du descendant avec le même paramètre avec l'ancêtre. Le mot-clé réintroduit est simplement supprimé l'avertissement du compilateur. P>

réintroduct est utilisé pour montrer les constructeurs d'ancêtres a> p> BlockQuote>

Dans la réponse de ce poste, c'est le mot clé de surcharge qui rend le constructeur de l'ancêtre encore disponible. P>

Ajout en réponse à la question de Ian dans son commentaire ci-dessous: P>

La première étape pour résoudre votre confusion est d'identifier les problèmes réels. Si nous examinons soigneusement vos messages, il deviendra évident que vous souhaitiez réellement résoudre deux problèmes en une étape. Les deux problèmes sont les suivants: p>

  1. Pour masquer le constructeur de l'ancêtre avec un nom spécifique Li>
  2. avoir plusieurs constructeurs avec un même nom spécifique dans le descendant. Li> ol>

    Bien qu'ils puissent ressembler à des problèmes simples, mais une inspection minutieuse a immédiatement enregistré votre tête que leurs natures sont exactement opposées les unes des autres. Problème 1 veut masquer une méthode / constructeur pendant que le problème 2 veut montrer non seulement une seule méthode / constructeur multiple. Donc, si vous les mélangez ensemble en une étape em> strong>, ils vont certainement s'annuler. Pas étonnant qu'ils vous donnent mal de tête ... :) p>

    La règle de base pour résoudre ces deux problèmes n'est pas de les mélanger en une étape. Cela signifie que nous avons besoin d'une classe intermédiaire pour résoudre le problème 1 et faire la surcharge des descendants de cette classe intermédiaire. Quelque chose comme ceci: p> xxx pré>

    à partir du code ci-dessus, tbasecellphone est la classe intermédiaire. Dans ce scénario, sa tâche est uniquement de masquer le constructeur Create of Tcomputer. Veuillez noter que vous ne doit pas em> strong> Utiliser le mot clé de surcharge ici ou la cachette sera annulée. Maintenant, après la cachette terminée, vous pouvez désormais libérer votre mot-clé de surcharge dans ses descendants pour obtenir plusieurs constructeurs avec le même nom. P>

    Pour vérifier, vous pouvez voir que le code suivant ne compilera pas: P >

       TCellPhone.Create('My Teapot');
    


3 commentaires

Je pense que j'ai trouvé le bogue dans Delphi. Le mot clé surcharge rend le constructeur de l'ancêtre encore disponible - quand ce n'est pas ce que c'est destiné. Il est destiné à autoriser deux surcharges dans tcellphone . Comment utiliser la surcharge pour autoriser plusieurs surcharges, mais ne pas autoriser la visibilité des méthodes de l'ancêtre? Iow: Comment puis-je cacher un constructeur d'ancêtre?


@Ian - ce ne serait pas un bug. Méthodes Surcharge: < I> "... Si la méthode redéclarée a une signature de paramètre différente de son ancêtre, elle surcharge la méthode héritée sans le cacher."


Ian, la surcharge vous permet d'avoir plusieurs routines ou méthodes avec le même nom. Ils ont seulement besoin d'avoir des paramètres différents. En ce qui concerne votre question, je verrai si je peux trouver un bon exemple.



1
votes

Eh bien, il semble que vous ne puissiez pas masquer une méthode / constructeur dans une classe où vous le surchargez également. Je suis venu avec ce minuscule "hack" pour réussir à masquer le constructeur à partir de TComputer xxx

dans cet exemple, TIPHONE n'aura que 1 constructeur disponible. Il casse cependant le polymorphisme (un prix à payer pour masquer le 2e constructeur de TCellphone). J'aimerais savoir si quelqu'un a trouvé un moyen de le faire sans casser le polymorphisme.

En outre, prenez note que ce n'est pas parce que le code Insight vous montre 4 "constructeurs" qu'il y ait bien 4 disponibles. J'ai noté que, pour chaque "dérogation" du rétroducteur, j'aurais 1 constructeur énuméré dans la perspicacité du code. Mais seul le constructeur descendant sera appelé dans cette situation.

Cet exemple se plaingera que le 2e constructeur de tecellphone cache celui de Thackcomputer, mais je pense que c'est un faux positif car celui de Thackcompagnateur est remplacé dans Tcellphone. (Bug de cas d'angle, car ce n'est pas un code de code très courant)


2 commentaires

C'est un tour très soigné. Je reçois le même problème que vous le faites (se plaindre que l'autre constructeur dans tcellphone masque celui de THACKComputer ). Expliquer pourquoi il se plaint est quelque chose qui mérite d'être demandé - dans une cinquième question sur les constructeurs à Delphi. La raison est parce que Je ne comprends pas pourquoi il se plaint , et c'est toujours une occasion d'apprendre.


Eh bien, comme je l'ai dit, ce n'est peut-être qu'un virus de cas d'angle. Une structure de code trompe le compilateur à donner des avertissements «faux positifs» de temps en temps.