web-dev-qa-db-fra.com

Comment créer une interface commune pour les classes avec différents sous-ensembles de membres

Je ne sais pas comment le mettre, mais je vais essayer d'être aussi clair que possible

J'ai un projet dans lequel je crée beaucoup de cours et que ces classes ont des propriétés et des méthodes courantes, mais ces méthodes pourraient avoir un code différent dans celui-ci,

J'ai donc décidé de faire une interface afin que je puisse hériter que dans toutes les classes et que toutes les classes auraient les mêmes méthodes en eux comme insert, update, delete Avec un code différent à l'intérieur de ces méthodes, mais cette astuce a été déplacée lorsque j'ai découvert que toutes les classes n'ont pas la même structure que certains ont une méthode d'insertion mais non mise à jour et si je hérite d'interface, je dois fournir une déclaration publique à tous les membres de cette interface qui Je ne veux pas.

Trick Deux, j'ai pensé aux classes abstraites créées un aussi, mais un même problème que tous les membres abstraits doivent être mis en œuvre avec le public.

Tellement longue histoire courte

Je veux créer une structure intryritable courante qui fonctionnerait comme une impression bleue non-capable pour les classes et pourrait être héritée en beaucoup de cours, mais dans de nombreuses classes, je ne veux pas mettre en œuvre tous les membres de cette structure

Remarque: Je peux faire de no-op (méthodes vides qui ne font rien, ou retourner une null, par exemple) car certains gars m'ont suggéré, mais ce n'est pas la solution que je recherche parce que ces membres inutiles seront visibles pendant l'intellaissance et c'est Ce que je veux éviter.

Comment puis je faire ça ?

7
yogi

La réponse simple consiste à créer plusieurs interfaces: Insertable, Updateable, Deleteable, etc. Toutefois, gardez à l'esprit que les classes ont des méthodes similaires ne signifie pas que besoin pour partager une structure d'héritage. Vous souhaitez uniquement utiliser l'héritage lorsque vous devez réutiliser le code qui appels Il, comme si vous avez besoin d'un conteneur contenant un tas d'objets différents de différents types et que vous devez appeler insert() sur tout dans ce conteneur.

11
Karl Bielefeldt

Ce que vous parlez est polymorphisme , qui signifie littéralement avoir de nombreuses formes.

Par exemple, vous pourriez avoir une classe de base appelée Animal, qui a une méthode appelée Eat(Food food);. Ensuite, vous pourriez avoir trois classes héritantes à partir de Animal comme Dog, Cat et Hen.

Toutes ces sous-classes devraient avoir Eat méthode (en remplaçant le membre de la classe de base), mais chacun peut avoir sa propre mise en œuvre (faire quelque chose différemment).

Ceci peut être atteint en utilisant héritage en héritant d'une superclasse (classe de base) ou en implémentant une ou plusieurs interfaces (comme @ooded dit, de nombreux petits interfaces au lieu d'une grande interface).

Une autre option qui me vient à l'esprit est d'implémenter Mixin en C #, mais je ne suis pas un pro là-dessus. Juste un indice;).

0
Saeed Neamati

Le problème est que toutes vos classes doivent se ressembler, car le programme qui les utilise ne sait pas (et ne veut pas vraiment veulent de savoir) lequel. Les méthodes de non-op peuvent être une bonne solution à ce problème, mais ils doivent avoir un sens. Si le programme d'appel appelle une, il ne devrait pas être gênant quand il ne fait rien.

L'étape suivante consiste à avoir des méthodes qui renvoient des capacités, de sorte que vous n'appelez pas les méthodes qu'un objet particulier ne peut pas gérer. Si CanFly renvoie false, l'appelant sait de ne pas appeler FlyToLA. Ceci, bien sûr, vous laisse avec beaucoup de méthodes de non-op qui ne devraient jamais être appelées - une situation désordonnée au mieux.

Le solution, je pense que toutes vos classes/interfaces ont une méthode GetFlight qui renvoie une instance Flight ("vol" peut être une classe ou interface - interface peut fonctionner mieux). Si cette méthode renvoie NULL, l'objet ne voler pas. Si cela renvoie un objet Flight, que objet contient toutes les méthodes concernées par le vol, ils sont donc là et disponibles si applicable et inexistant et inutilisable sinon.

Et vous auriez d'autres méthodes, peut-être plutôt beaucoup, tels que GetDrive, GetAccounting, GetPersonell, etc. Vous pourriez même les nicher, avec le Accounting Interface comportant des méthodes plus "Obtenir" de lot pour sous-ensembles de comptabilité. Il y a beaucoup de variations sur ce thème.

0
RalphChapin

En .NET, si une interface hérite d'autres interfaces, une classe qui implémente les interfaces constitutives peut être considérée comme dans la mise en œuvre de l'interface combinée simplement en le déclarant comme une, sans nécessiter d'effort de codage supplémentaire. Il pourrait donc être plus pratique d'avoir IThis, IThat et IThisOrThat _ interfaces que d'avoir une interface unifiée "fait tout", puisque les classes qui ne peuvent gérer que l'un des Les interfaces n'ont pas besoin de mettre en œuvre des talons pour les méthodes d'interface qu'ils ne peuvent pas gérer. En outre, code qui nécessite des objets pour gérer les deux interfaces au moment de la compilation peut exiger de tels objets en acceptant un paramètre de type IThisOrThat.

Il y a quelques limitations avec cette approche, cependant:

  1. Bien qu'il puisse autoriser le code de sécurité sans faute de sécurité sans taper, il n'y a aucune façon de spécifier à distance, de spécifier qu'une collection contient des objets qui implémentent plusieurs interfaces (par exemple, {ITHIS, ITHAT}), à moins que tous les types simples souhaitent utiliser l'implémentation une interface composite qui inclut toutes les interfaces dont on a besoin. Les génériques peuvent aider beaucoup avec des paramètres et des variables locales, mais peuvent être moins utiles avec des collections de type mixte.
  2. Le code peut contenir des objets non seulement pour elle-même, mais également dans le but de les donner à un autre code. Le code pourrait accepter un objet qui est tenu de mettre en œuvre "ititis" et un délégué qui devrait accepter l'objet transmis. Si le type de paramètre de l'objet transbordé est "ithis", le code ne sera pas en mesure de le transmettre à un délégué qui s'attend à une "Ithisorthat", même si l'instance dépassée implémente la dernière interface. L'utilisation de génériques peut aider ici, mais elles ne font pas toujours de choses totalement lisses.
  3. Parfois, le code peut avoir des cas dont les capacités exactes peuvent varier; Dans certains cas, des instances pourraient inclure des méthodes pour produire des instances plus capables. Par exemple, une classe immuable peut avoir une fonction `asmutable` qui retournerait une instance de classe mutable initialisée avec des données de l'immuable. Il peut être plus utile d'avoir des champs de type `imaybemutablefoo", qui est mis en œuvre par les classes mutables et immuables et comprend à la fois des méthodes "getter" et "getter", que pour avoir les champs de type `iReadablefoo` qui comprend un getter Mais pas de réglage et besoin d'un typast à tout moment souhaite écrire sur le champ, même après avoir testé que le champ contient un objet mutable.

J'aime l'approche d'interface composite, mais avoir des interfaces semi-composites (qui implémentent d'autres interfaces, mais elles ne sont pas garanties utilement) peuvent également être utiles.

0
supercat