Question

Si j'ai plusieurs sous-classes de quelque chose, et un algorithme qui fonctionne sur les instances de ces sous-classes, et si le comportement de l'algorithme varie légèrement en fonction de ce sous-classe particulière une instance est, alors la voie orientée objet le plus habituel de faire est d'utiliser des méthodes virtuelles.

Par exemple, si les sous-classes sont des noeuds DOM, et si l'algorithme est d'insérer un nœud enfant, cet algorithme diffère selon que le nœud parent est un élément DOM (qui peut avoir des enfants) ou le texte DOM (qui ne peut pas .): et si la méthode de insertChildren peut être virtuel (ou abstrait) dans la classe de base de DomNode, et mis en oeuvre différemment dans chacune des sous-classes de DomElement et DomText

Une autre possibilité est de donner les cas une propriété commune, dont la valeur peut être lu: par exemple l'algorithme peut lire la propriété nodeType de la classe de base DomNode; ou pour un autre exemple, vous pourriez avoir différents types (sous-classes) de paquet de réseau, qui partagent un en-tête de paquet commun, et vous pouvez lire l'en-tête de paquet pour voir quel type de paquet est.

Je ne l'ai pas utilisé des informations d'exécution de type beaucoup de temps, y compris:

  • Les mots-clés is et as en C #
  • Downcasting
  • La méthode Object.GetType en dot net
  • L'opérateur typeid en C ++

Quand je l'ajout d'un nouvel algorithme qui dépend du type de sous-classe, je tends plutôt que d'ajouter une nouvelle méthode virtuelle à la hiérarchie des classes.

Ma question est, quand il est approprié d'utiliser les informations de type d'exécution, au lieu des fonctions virtuelles?

Était-ce utile?

La solution

Quand il n'y a pas d'autre solution. Les méthodes virtuelles sont toujours préférées, mais parfois ils ne peuvent pas être utilisés. Il y a deux raisons pour lesquelles cela pourrait se produire mais la plus commune est que vous ne disposez pas du code source des classes que vous voulez travailler avec ou vous ne pouvez pas les changer. Cela se produit souvent lorsque vous travaillez avec l'ancien système ou avec bibliothèque commerciale source fermée.

Dans .NET, il peut arrive aussi que vous devez charger de nouvelles assemblées à la volée, comme plug-ins et vous avez généralement pas de cours de base, mais doivent utiliser quelque chose comme duck typing.

Autres conseils

En C ++, parmi d'autres cas obscurs (qui traitent principalement avec des choix de conception inférieurs), RTTI est un moyen de mettre en œuvre ce qu'on appelle méthodes multi-.

Cette construction ( « est » et « comme ») sont très familiers pour les développeurs Delphi, car les gestionnaires d'événements habituellement des objets baissés à un ancêtre commun. Pour exemple d'événement OnClick passe le seul argurment Sender: TObject quel que soit le type de l'objet, que ce soit TButton, TListBox ou tout autre. Si vous voulez en savoir un peu plus sur cet objet, vous devez y accéder via « comme », mais afin d'éviter une exception, vous pouvez vérifier avec « est » avant. Cette downcasting permet la liaison de type de conception des objets et des méthodes qui ne pouvaient pas être possible avec un contrôle strict de type de classe. Imaginez que vous voulez faire la même chose si l'utilisateur clique sur le bouton ou ListBox, mais s'ils nous fournissent différents prototypes de fonctions, il ne pouvait pas être possible de les lier à la même procédure.

Dans le cas plus général, un objet peut appeler une fonction qui informe que l'objet par exemple a changé. Mais à l'avance, il quitte la destination la possibilité de le connaître « personnellement » (et à travers comme), mais pas nécessairement. Il le fait en passant soi comme un ancêtre le plus commun de tous les objets (TObject dans le cas Delphi)

dynamic_cast <>, si je me souviens bien, est en fonction RTTI. Certaines interfaces externes obscures peuvent également compter sur RTTI quand un objet est passé à travers un pointeur vide (pour une raison quelconque que pourrait se produire).

Cela étant dit, je ne l'ai pas vu typeof () dans la nature en 10 ans de travaux d'entretien pro C ++. (Heureusement).

Vous pouvez consulter plus efficace C # pour un cas où la vérification du type d'exécution est OK.

  

Article 3. Les algorithmes génériques sont spécialisés   Utilisation du type Vérification à l'exécution

     

Vous pouvez facilement réutiliser les médicaments génériques par   spécifiant simplement de nouveaux paramètres de type.   Une nouvelle instanciation avec nouveau type   paramètres signifie un nouveau type comportant   des fonctionnalités similaires.

     

Tout cela est très bien, parce que vous écrivez   moins de code. Cependant, étant parfois   des moyens plus génériques qui ne prennent pas   avantage d'un plus précis, mais   nettement supérieur, l'algorithme. Le C #   règles linguistiques prennent en compte.   Il suffit pour vous de reconnaître   que votre algorithme peut être plus   efficaces lorsque les paramètres de type   ont une plus grande capacité, puis   écrire ce code spécifique. En outre,   la création d'un second type générique   spécifie des contraintes différentes   ne fonctionne pas toujours. Générique   sont basées sur la instanciations   type d'un objet lors de la compilation, et   pas le type d'exécution. Si vous ne parvenez pas à   tenir compte, vous pouvez manquer   efficacité possibles.

Par exemple, supposons que vous écrivez une classe qui fournit une énumération inverse l'ordre sur une séquence d'éléments représentés par IEnumerable . Pour l'énumérer, vous pouvez itérer en arrière et de copier des éléments dans une collection intermédiaire avec accès indexeur comme List et que d'énumérer cette collection en utilisant l'accès arrière indexeur. Mais si votre original IEnumerable est IList pourquoi ne pas en profiter et de fournir de manière plus performante (sans copier à la collecte intermédiaire) pour itérer les éléments en arrière. Donc, fondamentalement, il est un spécial, nous pouvons profiter de, mais en offrant le même comportement (séquence itérer arrière).

Mais en général, vous devriez examiner attentivement la vérification du type d'exécution et veiller à ce qu'il ne viole pas Liskov Substituion Principe.

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