L’importance des interfaces en Java

Disons que nous avons deux classes, Tiger et Aeroplane . Une chose en commun pour ces deux types est la vitesse. Je sais qu’il serait illogique de créer une super classe ClassWithSpeed et d’en déduire les sous-classes Aeroplane et Tiger . Au lieu de cela, il est préférable de créer une interface contenant la méthode speed() , puis de l’implémenter dans Aeroplane et Tiger . Je comprends ça. Mais, nous pouvons faire la même chose sans interfaces. Nous pourrions définir la méthode speed() dans Aeroplane et method speed() dans Tiger . Le seul défaut (peut-être très important) serait de ne pas pouvoir “atteindre” les objects de Tiger et d’ Aeroplane par une référence d’interface.

Je suis débutant en Java et OOP, et je vous serais très reconnaissant si quelqu’un m’expliquait le rôle des interfaces. À votre santé!

Ses:

 public int howFast(Airplane airplane) { return airplane.speed(); } public int howFast(Tiger tiger) { return tiger.speed(); } public int howFast(Rocket rocket) { return rocket.speed(); } public int howFast(ThingThatHasntBeenInventedYet thingx) { // wait... what? HOW IS THIS POSSIBLE?! return thingx.speed(); } ... 

contre

 public int howFast(Mover mover) { return mover.speed(); } 

Maintenant, imaginez que vous howFast revenir en arrière et changer toutes les fonctions de howFast à l’avenir.

Interface ou non, chaque classe devra implémenter ou hériter de la méthode speed() . Une interface vous permet d’utiliser plus facilement ces classes disparates, car chacune d’entre elles a promis de se comporter d’une certaine manière. Vous allez appeler speed() , et ils renverront un int , vous n’avez donc pas besoin d’écrire des méthodes distinctes pour chaque classe possible.

Lorsque vous trouvez que vous devez gérer la vitesse différemment en raison d’une percée dans la physique relativiste, il vous suffit de mettre à jour les méthodes qui appellent speed() . Lorsque votre arrière-petite-fille écrit un cours pour HyperIntelligentMonkeyFish , elle ne doit pas démonter votre ancien fichier binary et apporter des modifications pour que votre code puisse surveiller et contrôler son armée mutante. Elle doit seulement déclarer que HyperIntelligentMonkeyFish implements Mover .

Les interfaces permettent à Java, car il est typé statiquement, de contourner les limitations de l’inheritance multiples au degré jugé intéressant par les concepteurs de langage.

Dans un langage dynamic (comme Python, Ruby, etc.), vous pouvez simplement appeler la méthode de vitesse sur n’importe quel object arbitraire et la découvrir à l’exécution si elle existe ou non.

Java, par contre, est typé statiquement, ce qui signifie que le compilateur doit convenir que la méthode sera présente à l’avance. La seule façon de faire cela sur les classes qui ne partagent pas d’ascendance commune, et qui ont uniquement Object en commun, est une interface.

Comme les objects peuvent implémenter un nombre arbitraire d’interfaces, cela signifie que vous bénéficiez de l’inheritance multiple (un object unique pouvant représenter plusieurs objects différents pour différentes méthodes) sans qu’il y ait d’inconvénient (des implémentations contradictoires dans les deux super-classes).

Avec Java 8, les concepteurs du langage ont conclu que les interfaces sans aucune implémentation étaient trop ressortingctives (elles n’aimaient pas ma solution, je suppose ;-)), elles permettent donc une implémentation par défaut, élargissant ainsi les options d’inheritance multiples des interfaces , tout en essayant d’éviter le problème d’implémentation en conflit via un ensemble complexe de règles de priorité, de sorte qu’il existe une implémentation par défaut non ambiguë à exécuter.

J’essaie d’expliquer l’avantage de l’interface avec l’exemple suivant:

Supposons que vous ayez une autre classe où vous devez utiliser le tigre ou l’avion comme paramètre. Donc, en utilisant l’interface, vous pouvez appeler en utilisant

 someObject.someMethod(ClassWithSpeed) 

mais si vous n’utilisez pas l’interface, vous pouvez utiliser

 someObject.someMethod(Tiger) someObject.someMethod(AeroPlane) 

Maintenant que devriez-vous faire? Votre réponse probable sera: "I will use two overloaded method".

C’est correct jusqu’ici, mais

Disons que vous devez append plus d’options (par exemple, voiture, cycle, lapin, tortue … 100 autres). Alors, que ferez-vous pour faire le changement de votre code existant? vous devrez changer beaucoup de choses ..

L’exemple global ci-dessus n’a qu’un but. C’est-à-dire

“nous avons besoin d’une interface pour créer une conception meilleure, réutilisable et orientée object”

NB

  1. Si vous êtes sûr que le programme est trop petit et que vous n’aurez jamais besoin de les changer, je pense qu’il est correct d’implémenter sans interface

La définition d’une interface vous permet de définir des méthodes qui fonctionnent non seulement sur Airplane et Tiger, mais également sur d’autres classes partageant la même interface.

Par exemple, disons que votre interface est IObjectWithSpeed. Vous pouvez ensuite définir une méthode comme celle-ci – dans une seule classe qui opère sur des objects IObjectWithSpeed.

  public double calculateSecondsToTravel( IObjectWithSpeed obj, double distance ) { return distance / obj.getSpeed(); } 

Les interfaces nous permettent de satisfaire au principe d’ouverture / de fermeture – ouvert pour extension, mais fermé pour modification. L’implémentation unique de la méthode ci-dessus n’a pas besoin d’être modifiée au fur et à mesure que de nouvelles classes implémentent IObjectWithSpeed ​​sont définies.

Je veux entrer dans beaucoup de détails théoriques, mais je vais essayer d’expliquer en utilisant cet exemple.

Considérez JDBC API . C’est l’API utilisée pour gérer les options liées à la firebase database dans Java. Maintenant, il y a tellement de bases de données dans l’indussortinge. Comment pourrait-on écrire des pilotes pour cela? Eh bien, l’approche rapide et sale peut consister à écrire sa propre implémentation en utilisant nos propres classes et API.

Mais pensez du sharepoint vue du programmeur. Vont-ils commencer à apprendre l’API de DATABASE DRIVER en utilisant différentes bases de données? La réponse est non.

Alors, quelle est la solution au problème? Ayez juste une API bien définie que tout le monde peut étendre pour sa propre implémentation.

Dans l’API JDBC, il existe des interfaces qui sont Connection, ResultSet, PreparedStatement, Statement, etc. Maintenant, chaque fournisseur de firebase database implémentera l’interface et écrira sa propre implémentation pour cela. Résultat ? : Réduction des efforts du développeur et facilité de compréhension.

Maintenant, en quoi consiste cette implémentation personnalisée? C’est simple. Ils font quoi, prennent par exemple l’interface ResultSet et l’implémentent et, quelle que soit la méthode renvoyée par ResultSet, retournez l’interface CLASSE qui implémente ResultSet comme ceci

ResultSet rs = new ResultSetImpl (); // c’est ce qu’ils font en interne.

Donc, l’interface est comme les contrats. Ils définissent ce que votre classe est capable de faire et offrent une flexibilité à votre application. Vous pouvez créer vos propres API en utilisant des interfaces correctement.

J’espère que cela vous aidera.

Une interface n’est pas simplement une signature de méthode.

C’est un type qui représente un contrat. Le contrat est la chose, pas la signature de la méthode. Lorsqu’une classe implémente une interface, c’est parce qu’il existe un contrat pour un comportement partagé que la classe a intérêt à implémenter en tant que type. Ce contrat est implémenté via les membres spécifiés, qui sont généralement des corps de méthodes, mais peut également inclure des champs finaux statiques.

Il peut être vrai qu’un tigre et un avion peuvent tous deux être exprimés comme un type avec un comportement commun implémenté par la vitesse () … et si oui, l’interface représente le contrat pour exprimer ce comportement.

En plus d’être descriptives pour les fonctionnalités de ces classes, les méthodes d’une interface peuvent être utilisées sans aucune connaissance des classes qui l’implémentent, même pour les classes qui n’ont pas encore été définies.

Par exemple, si vous aviez besoin d’une classe Transport qui calcule des routes efficaces, vous pourriez lui atsortingbuer une classe qui implémente ClassWithSpeed tant que paramètre et utiliser sa méthode speed() pour calculer ce dont il a besoin. De cette façon, vous pouvez l’utiliser avec notre Aeroplane classe, mais aussi avec toutes les classes que nous définissons plus tard, par exemple Boat . Java veillera à ce que si vous souhaitez utiliser une classe en tant que paramètre pour Transport il implémentera ClassWithSpeed , et que toute classe implémentant ClassWithSpeed implémente la méthode speed() pour pouvoir l’utiliser.

L’interface (en tant que construction de langage) est utilisée par le compilateur pour prouver que l’appel de méthode est valide et vous permet d’avoir des classes dépendantes interagissant avec la classe d’implémentation tout en ayant le moins de connaissances possible sur la classe d’implémentation.

C’est une question très large pour donner une réponse simple. Je peux recommander un livre Conception orientée interface: avec des motifs . Il explique toute la puissance des interfaces. Et pourquoi ne pas les éviter.

Avez-vous essayé d’utiliser la composition à la place? Si je veux que 2 classes différentes héritent des mêmes capacités, j’utilise une classe qui utilise un object du type en utilisant des classes abstraites et en vérifiant les instances. Les interfaces sont utiles pour forcer les méthodes à être incluses dans la classe, mais ne nécessitent aucune implémentation ou 2 équipes de codeurs doivent travailler sur des zones de codage différentes.

 Class Tiger { public MovingEntity mover; public Tiger(){ mover.speed=30; mover.directionX=-1; mover.move(mover); } } Class Plane { public MovingEntity mover; public Plane(){ mover.speed=500; mover.directionX=-1; mover.move(mover); } Abstract Class Moverable(){ private int xPos; private int yPos; private int directionX; private int directionY; private int speed; Class MovingEntity extends Moverable { public void move(Moverable m){ if(m instanceof Tiger){ xPos+=directionX*speed; yPos+=directionY*speed; }else if(m instanceof Plane){ xPos+=directionX*speed; yPos+=directionY*speed; } } 

Au niveau de la langue, la seule utilisation des interfaces est, comme vous l’avez mentionné, de pouvoir faire référence à différentes classes de manière commune. Au niveau des personnes, cependant, l’image est différente: IMO Java est solide lorsqu’il est utilisé dans de grands projets où la conception et la mise en œuvre sont effectuées par des personnes distinctes, souvent issues de sociétés distinctes. Maintenant, au lieu d’écrire une spécification sur un document Word, les architectes système peuvent créer un groupe de classes que les implémenteurs peuvent ensuite insérer directement dans leurs IDE et commencer à travailler dessus. En d’autres termes, il est plus pratique au lieu de déclarer que “la classe X implémente les méthodes Y et Z pour qu’elle soit utilisée dans le but A, juste pour dire que” la classe X implémente l’interface A ”

Parce que créer une interface vous donne un polymorphism , à travers toutes ces classes, à savoir Tiger et Airplane.

Vous pouvez étendre à partir d’une classe (abstraite ou concrète) lorsque la fonctionnalité de la classe de base sera également au cœur des fonctionnalités de votre classe enfant.

Vous utilisez des interfaces lorsque vous souhaitez append une fonctionnalité améliorée à votre classe en plus de ses fonctionnalités principales. Donc, l’utilisation d’interfaces vous donnerait un polymorphism même si ce n’est pas la fonctionnalité principale de votre classe (car vous avez conclu un contrat en implémentant l’interface). C’est un avantage énorme par rapport à la création d’une méthode speed () avec chaque classe.