Dans la plupart des codes Java, je vois des gens déclarer des objets Java comme ceci:
Map<String, String> hashMap = new HashMap<>();
List<String> list = new ArrayList<>();
au lieu de:
HashMap<String, String> hashMap = new HashMap<>();
ArrayList<String> list = new ArrayList<>();
Pourquoi y a-t-il une préférence pour définir l'objet Java à l'aide de l'interface plutôt que l'implémentation qui sera réellement utilisée?
Réponses:
La raison en est que l'implémentation de ces interfaces n'est généralement pas pertinente lors de leur manipulation, donc si vous obligez l'appelant à passer un
HashMap
à une méthode, alors vous obligez essentiellement l'implémentation à utiliser. Donc, en règle générale, vous êtes censé gérer son interface plutôt que la mise en œuvre réelle et éviter les douleurs et les souffrances qui pourraient entraîner la modification de toutes les signatures de méthodeHashMap
lorsque vous décidez de les utiliser à laLinkedHashMap
place.Il faut dire qu'il y a des exceptions à cela lorsque la mise en œuvre est pertinente. Si vous avez besoin d' une carte lorsque l' ordre est important, alors vous pouvez demander un
TreeMap
ouLinkedHashMap
à transmettre, ou mieux encore ,SortedMap
qui ne précise pas une implémentation spécifique. Cela oblige l'appelant à passer nécessairement un certain type d'implémentation de Map et indique fortement que l'ordre est important. Cela dit, pourriez-vous passer outreSortedMap
et passer un non trié? Oui, bien sûr, mais attendez-vous à ce que de mauvaises choses se produisent.Cependant, les meilleures pratiques dictent toujours que si ce n'est pas important, vous ne devez pas utiliser des implémentations spécifiques. C'est vrai en général. Si vous traitez
Dog
etCat
que vous en dérivezAnimal
, afin d'utiliser au mieux l'héritage, vous devriez généralement éviter d'avoir des méthodes spécifiques àDog
ouCat
. Plutôt toutes les méthodes dansDog
ouCat
devraient remplacer les méthodes dansAnimal
et cela vous évitera des problèmes à long terme.la source
SortedMap
nonTreeMap
.SortedMap
est l'une des nombreuses implémentations qui traitent de la commande. C'est d'ailleurs le point.TreeMap
commande également les articles en fonction de l'implémentation de la cléComparable
ou d'uneComparator
interface donnée .LinkedHashMap
ne met pas en œuvreSortedMap
. Les seules sous-classes deSortedMap
sontConcurrentSkipListMap
etTreeMap
.Selon les mots de Layman:
La même raison pour laquelle les fabricants d'appareils électriques ont construit leurs produits avec des fiches électriques au lieu de simplement décortiquer les câbles, et les maisons sont équipées de prises murales au lieu de câbles décollés qui dépassent du mur.
En utilisant des prises standard à la place, ils permettent de brancher les mêmes appareils dans n'importe quelle prise compatible dans la maison.
Du point de vue de la prise murale, peu importe si vous branchez un téléviseur ou une chaîne stéréo.
Cela rend à la fois l'appareil et la prise plus utiles.
Prenons par exemple une méthode qui accepte une carte comme argument.
La méthode fonctionnera indépendamment du fait que vous lui passiez un HashMap ou un LinkedHashMap, tant qu'il s'agit d'une sous-classe de Map.
C'est le principe de substitution de Liskov .
Dans l'exemple de code que vous avez donné, cela signifie que vous pouvez ultérieurement, pour une raison quelconque, modifier l'implémentation concrète de Hash et vous n'aurez pas besoin de modifier le reste du code.
Le problème avec le logiciel est que, comme il est relativement facile de changer les choses plus tard sans gaspiller de briques ou de mortier, les gens supposent que ce genre de prévoyance ne vaut pas la peine. Mais la réalité nous a montré que la maintenance logicielle coûte très cher.
la source
C'est pour suivre le principe de ségrégation d'interface (le «je» dans SOLID ). Il empêche le code qui utilise ces objets de dépendre des méthodes des objets dont il n'a pas besoin, ce qui rend le code moins couplé et donc plus facile à modifier.
Par exemple, si vous découvrez plus tard que vous en avez vraiment besoin
LinkedHashMap
, vous pouvez effectuer cette modification en toute sécurité sans affecter aucun autre code.Cependant, il y a un compromis à faire, car vous limitez artificiellement le code qui peut prendre votre objet en paramètre. Disons qu'il y a une fonction quelque part qui nécessite une
HashMap
pour une raison quelconque. Si vous retournez unMap
, vous ne pouvez pas passer votre objet dans cette fonction. Vous devez équilibrer la probabilité que dans le futur, vous ayez besoin des fonctionnalités supplémentaires de la classe la plus concrète avec le désir de limiter le couplage et de garder votre interface publique aussi petite que possible.la source
Le fait de contraindre la variable à une interface garantit qu'aucune des utilisations de cette variable n'utilisera
HashMap
des fonctionnalités spécifiques qui peuvent ne pas exister sur l'interface, de sorte que l'instance peut être modifiée sans souci plus tard par une implémentation différente tant que la nouvelle instance implémente également la interface.Pour cette raison, chaque fois que vous souhaitez utiliser une interface d'objets, il est toujours recommandé de déclarer vos variables comme interface et non comme implémentation particulière, cela vaut pour tous les types d'objets que vous pouvez utiliser et qui ont une interface. La raison pour laquelle vous le voyez souvent est que beaucoup de gens ont intégré cela comme une habitude.
Cela dit, il n'est pas dangereux de ne pas utiliser parfois les interfaces, et la plupart d'entre nous ne respectent pas toujours cette règle, sans réel préjudice. C'est juste une bonne pratique à respecter lorsque vous avez le sentiment que le code peut être modifié et que vous avez besoin de maintenance / croissance à l'avenir. C'est moins une préoccupation lorsque vous piratez du code que vous ne soupçonnez pas d'avoir une longue durée de vie ou qui a beaucoup d'importance. En outre, enfreindre cette règle a généralement une petite conséquence que le changement d'implémentation en une autre peut nécessiter un peu de refactoring, donc si vous ne la suivez pas toujours, vous ne vous blesserez pas beaucoup, bien qu'il n'y ait pas vraiment de mal à la suivre non plus .
la source