Par exemple:
Dire que j'ai des classes A
, B
, C
. J'ai deux interfaces, appelons-les IAnimal
et IDog
. IDog
hérite de IAnimal
. A
et B
sont IDog
s, tandis que C
ne l'est pas, mais c'est un IAnimal
.
La partie importante est qu'elle IDog
ne fournit aucune fonctionnalité supplémentaire. Il est uniquement utilisé pour autoriser A
et B
, mais pas C
, être passé en argument à certaines méthodes.
Est-ce une mauvaise pratique?
object-oriented
interfaces
Kendall Frey
la source
la source
IAnimal
etIDog
sont de terribles noms de tautologie!MyProject.Data.IAnimal
etMyProject.Data.Animal
sont meilleurs queMyProject.Data.Interfaces.Animal
etMyProject.Data.Implementations.Animal
Interface
ouImplementation
, que ce soit dans un préfixe répétitif ou dans un espace de noms, c'est une tautologie de toute façon et viole DRY.Dog
est tout ce dont vous devez vous soucier.PitBull extends Dog
n'a pas besoin de redondance d'implémentation non plus, le motextends
me dit tout ce que j'ai besoin de savoir, lisez le lien que j'ai posté dans mon commentaire d'origine.Réponses:
Interface qui n'a aucun membre ou qui a exactement les mêmes membres avec une autre interface héritée de la même interface appelée Interface de marqueur et que vous l'utilisez comme marqueur.
Ce n'est pas une mauvaise pratique mais l'interface peut être remplacée par des attributs (annotations) si la langue que vous utilisez la prend en charge.
Je peux dire en toute confiance que ce n'est pas une mauvaise pratique parce que j'ai vu un modèle "d'interface de marqueur" à forte utilisation dans le projet Orchard
Voici un exemple du projet Orchard.
Veuillez vous référer à l' interface des marqueurs .
la source
C
à une méthode qui attend unIDog
.Kennel
classe qui stocke une liste deIDog
s.Oui, c'est une mauvaise pratique dans presque toutes les langues.
Les types ne sont pas là pour coder les données; ils sont une aide pour prouver que vos données vont là où elles doivent aller et se comportent comme elles doivent se comporter. La seule raison de sous-taper est si un comportement polymorphe change (et pas toujours alors).
Puisqu'il n'y a pas de saisie, ce qu'un IDog peut faire est implicite. Un programmeur pense une chose, un autre en pense une autre et les choses tombent en panne. Ou les choses qu'il représente augmentent à mesure que vous avez besoin d'un contrôle plus fin.
[modifier: clarification]
Ce que je veux dire, c'est que vous faites une logique basée sur l'interface. Pourquoi certaines méthodes ne peuvent-elles fonctionner qu'avec des chiens et d'autres avec n'importe quel animal? Cette différence est un contrat implicite puisqu'il n'y a aucun membre réel qui fournit la différence; aucune donnée réelle dans le système. La seule différence est l'interface (d'où le commentaire «pas de frappe»), et ce que cela signifie différera entre les programmeurs. [/Éditer]
Certains langages fournissent des mécanismes de traits là où ce n'est pas trop mal, mais ceux-ci ont tendance à se concentrer sur les capacités, pas sur le raffinement. J'ai peu d'expérience avec eux, donc je ne peux pas parler des meilleures pratiques là-bas. En C ++ / Java / C # cependant ... pas bon.
la source
Kennel
classe qui stocke une liste deIDog
s.Je ne connais bien que C #, donc je ne peux pas dire cela pour la programmation OO en général, mais comme exemple C #, si vous devez catégoriser les classes, les options évidentes sont les interfaces, la propriété enum ou les attributs personnalisés. Habituellement, je choisirais l'interface, peu importe ce que les autres pensent.
la source
Il n'y a rien de mal à avoir une interface qui hérite d'une autre interface sans ajouter de nouveaux membres, si toutes les implémentations de cette dernière interface sont censées être capables de faire utilement des choses que certaines implémentations de la première peuvent ne pas faire. En effet, c'est un bon modèle qui à mon humble avis aurait dû être utilisé plus dans des choses comme le .net Framework, d'autant plus qu'un implémenteur dont la classe satisferait naturellement les contraintes impliquées par l'interface plus dérivée peut indiquer que simplement en implémentant l'interface plus dérivée , sans avoir à modifier le code ou les déclarations d'implémentation des membres.
Par exemple, supposons que j'ai les interfaces:
Une implémentation de
IImmutableFoo.AsImmutable()
devrait se retourner; une implémentation de classe mutableIMaybeMutableFoo.AsImmutable()
devrait renvoyer un nouvel objet profondément immuable contenant un instantané des données. Une routine qui veut stocker un instantané des données contenues dans unIMaybeMutableFoo
pourrait offrir des surcharges:Dans les cas où le compilateur ne sait pas que la chose à stocker est un
IImmutableFoo
, il appelleraAsImmutable()
. La fonction doit retourner rapidement si l'élément est déjà immuable, mais un appel de fonction via une interface prend encore du temps. Si le compilateur sait que l'élément est déjà unIImmutableFoo
, il peut ignorer l'appel de fonction inutile.la source