Forum |  HardWare.fr | News | Articles | PC | Prix | S'identifier | S'inscrire | Aide | Shop Recherche
1392 connectés 

  FORUM HardWare.fr
  Programmation
  Java

  Polymorphisme et intérêt des interfaces

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Polymorphisme et intérêt des interfaces

n°2293505
brosylen
Posté le 11-12-2016 à 14:02:11  profilanswer
 

Bonjour à tous !  :hello:  
 
J'essaie en ce moment de saisir les concepts de la POO avec Java, mais j'ai quelques problèmes (je ne suis pas le premier) avec les interfaces.
J'ai écumé openclassrooms et d'autres sites qui expliquent tous l'intérêt de l'interface, mais je garde une certaine difficulté à les comprendre. Tout n'est pas clair.
De ce que j'ai saisi, une interface permet, en quelque sorte, de faire hériter des méthodes abstraites aux classes qui l'implémentent. Mais je ne vois pas alors la différence que cela peut avoir avec une simple classe mère. J'ai aussi quelques problèmes à comprendre comment utiliser au mieux le polymorphisme.
Admettons par exemple que je code un simple pacman. Voici le diagramme de classes (simplifié) que j'ai pu concevoir (j'ai omis les constructeurs par souci de clarté).

  • Chaque acteur du jeu a une position et une direction, ainsi qu'une méthode move() pour se déplacer dans la direction choisie.
  • La direction de Pacman est contrôlée par l'utilisateur, et il possède une méthode eatPellets() pour manger les petites boules.
  • Les fantômes choisissent leur direction seuls, grâce à la méthode chooseTarget(), qui choisit une cible à atteindre sur le terrain en fonction de leurs intelligence artificielles propres.

https://s28.postimg.org/y7x4bestp/Diagrammedeclasses.png
 
Si j'ai bien compris, dans le code, chaque fantôme pourra être instancié dans un objet Ghost comme suit :

Code :
  1. Ghost blinky = new Blinky();
  2. Ghost pinky = new Pinky();
  3. Ghost inky = new Inky();
  4. Ghost clyde = new Clyde();


Ce qui me permettrait alors de les manipuler dans un tableau afin, par exemple, de les faire bouger tous d'un coup :

Code :
  1. Ghost[] ghosts = {blinky, pinky, inky, clyde};
  2. for (int i = 0; i < ghosts.length(); i++) {
  3.     ghosts[i].move();
  4. }


En revanche, si je comprends bien le polymorphisme, je ne peux instancier pacman que comme ceci :

Code :
  1. Pacman pacman = new Pacman();
  2. // La déclaration suivante échouerait car la classe Pacman possède une méthode qu'Agent ne possède pas
  3. Agent pacman2 = new Pacman();


Ai-je bien compris comment fonctionnait le polymorphisme ?
Dans ce cas-ci, transformer la classe Ghost en interface, faire hériter mes 4 fantômes de Agent directement et leur faire implémenter l'interface Ghost est-il faisable ? Cela aurait-il du sens ? Si oui, quels sont les avantages que cela apporterait ?

mood
Publicité
Posté le 11-12-2016 à 14:02:11  profilanswer
 

n°2293513
DDT
Posté le 12-12-2016 à 01:06:21  profilanswer
 

Tu peux hériter de classes concrètes, pas de soucis, mais ici du coup tu pourrais aussi instancier des objets de type Agent ou Ghost, ce que tu ne veux pas normalement.
Ton exemple aurait plus de sens avec des classes abstraites pour ces deux classes, dans le but de partager l'implémentation de certaines méthodes tout en interdisant leur instanciation directe.
Quant aux interfaces, depuis Java 8 elles peuvent fournir une implémentation par défaut des méthodes, mais une classe abstraite peut en plus définir un constructeur et surtout ici, te permettrait d'avoir des membres positionX, positionY, ... non finaux.

 

Tu peux parfaitement instancier une classe non-abstraite et l'assigner à une variable d'un type parent (abstrait ou non):

Code :
  1. Agent pacman2 = new Pacman();
  2. pacman2.move(); // ok, défini pour Agent
  3. pacman2.eatPellets(); // pas possible
  4. ((Pacman) pacman2).eatPellets(); // ok
 

Si tu veux un bon exemple, dans ton IDE ou dans la Javadoc jette un œil à java.util.List, AbstractList et ArrayList.


Message édité par DDT le 12-12-2016 à 01:08:23

---------------
click clack clunka thunk
n°2293529
gelatine_v​elue
Posté le 12-12-2016 à 15:40:09  profilanswer
 

brosylen a écrit :


// La déclaration suivante échouerait car la classe Pacman possède une méthode qu'Agent ne possède pas
Agent pacman2 = new Pacman();

 

Non, cette déclaration est valide.

 

Une interface est un ensemble de comportements que doit avoir une classe, et c'est pourquoi une classe peut avoir plusieurs interfaces. On peut attendre d'elle plusieurs comportements. Pour pacman ce pourrait être d'être un agent (interface Agent) ET d'etre controlable par l'utilisateur (nouvelle interface UserMoveable par ex.)
Mais une interface peut avoir aussi 0 méthodes (google interfaces marqueurs). Une interface est un tag qui montre qu'on peut attendre d'une classe quelle se comporte d'une certaine manière, ou dit autrement, qu'elle implémente certaines méthodes.

 

Une classe abstraite sert à factoriser du code présent dans plusieurs classes similaires. En java on ne peut hériter que d'une classe. Une classe abstraite ne sert donc pas à définir un contrat d'interface mais plus à grouper du code entre plusieurs classes proches ou identiques, comme tes Ghosts.

 

Note que l'un n'empêche pas l'autre. Il serait logique que Ghost hérite de AbstractGhost pour factoriser le code commun, et que AbstractGhost implémente l'interface IGhost, qui définit les méthodes que le reste du programme peut s'attendre de voir un Ghost implémenter: le contrat d'interface.


Message édité par gelatine_velue le 12-12-2016 à 15:40:22

---------------
RIP Firefox OS :'(
n°2293533
DDT
Posté le 12-12-2016 à 16:02:11  profilanswer
 

Si tu préfixes le nom de tes interfaces avec I en Java je te mets un coup de pelle lors des revues de code. :o


---------------
click clack clunka thunk
n°2293542
gelatine_v​elue
Posté le 12-12-2016 à 19:50:55  profilanswer
 

DDT a écrit :

Si tu préfixes le nom de tes interfaces avec I en Java je te mets un coup de pelle lors des revues de code. :o

 

C'est pour etre le moins ambigu possible dans mon explication, j'etais SUR que qqun allait faire la remarque. :D
Donc petit aparte pour les novices: ne le faites pas selon avec qui vous codez, pas plus que mettre Abstract devant vos classes abstraites, ca peut ne pas passer.
Perso je m'en fous je m'adapte, je considere que c'est pas important.

Message cité 1 fois
Message édité par gelatine_velue le 12-12-2016 à 19:55:31

---------------
RIP Firefox OS :'(
n°2293553
bu47u96u99
Posté le 12-12-2016 à 23:03:43  profilanswer
 

gelatine_velue a écrit :


 
C'est pour etre le moins ambigu possible dans mon explication, j'etais SUR que qqun allait faire la remarque. :D
Donc petit aparte pour les novices: ne le faites pas selon avec qui vous codez, pas plus que mettre Abstract devant vos classes abstraites, ca peut ne pas passer.  
Perso je m'en fous je m'adapte, je considere que c'est pas important.


 
Pourtant checkstyle et PMD grognent quant il n'y a pas de Abstract devant les classes abstraites, je conseillerais plutôt de le mettre ainsi que Impl comme suffixe des implémentations d'interface...  ;)

n°2293554
antiseptiq​ueincolore
ni repris ni échangé
Posté le 13-12-2016 à 06:20:02  profilanswer
 

hmmm sur mon ancien projet, on doit trouver plusieurs centaines (milliers?) d'interfaces qui commencent par I.
On sait immédiatement si l'algo qui consomme les objets est générique ou spécialisé.
 
Ce serait quoi les bonnes raisons de ne pas mettre I?

Message cité 1 fois
Message édité par antiseptiqueincolore le 13-12-2016 à 06:20:17
n°2293563
DDT
Posté le 13-12-2016 à 11:21:51  profilanswer
 

Le C# c'est à côté. :spamafote:
 
Tous les projets sérieux en Java suivent les conventions de nommage du langage.
Regarde les dizaines/centaines de dépendances open source dans ton classpath... si ces projets y arrivent, pourquoi pas toi?
 
http://stackoverflow.com/a/2814831/2934360


---------------
click clack clunka thunk
n°2293603
antiseptiq​ueincolore
ni repris ni échangé
Posté le 13-12-2016 à 20:00:24  profilanswer
 

sujet très sensible  :D  un peu comme les réglages de sonarqube sur ce qui est acceptable ou pas.
et en général j'aime bien contester  :D je ne vais pas le faire  [:ddr555]

n°2293800
Harkonnen
Modérateur
SQL is evil
Posté le 17-12-2016 à 14:15:26  profilanswer
 

antiseptiqueincolore a écrit :


 
Ce serait quoi les bonnes raisons de ne pas mettre I?


Parce que c'est dérivé de la notation hongroise qui est devenue totalement inutile avec les langages typés, elle pollue le code et les yeux avec une information que l'utilisateur de ton interface n'a pas besoin de connaitre.


---------------
J'ai un string dans l'array (Paris Hilton)
mood
Publicité
Posté le 17-12-2016 à 14:15:26  profilanswer
 

n°2293824
antiseptiq​ueincolore
ni repris ni échangé
Posté le 18-12-2016 à 21:57:59  profilanswer
 

http://reho.st/https://www.jmdoudoux.fr/java/dej/images/collections_001.png
J'ai beaucoup de mal à savoir ce que je peux instancier là dedans....Sauf par habitude. (ils ont bien ajouté class ou interface pour qu'on sache  :whistle: )
 
Je suis d'accord qu'une interface est un type mais rajouter I devant, me dit immédiatement que ce type n'est pas instanciable (tout comme A).
C'est une information supplémentaire. A plus forte raison si ça a été fait par un autre développeur et que je dois me brancher sur son code (et qu'en plus je n'ai que 4 heures)
Je suis ouvert mais c'est une information dont je me sers réellement!
 
 

n°2293835
Harkonnen
Modérateur
SQL is evil
Posté le 19-12-2016 à 11:23:58  profilanswer
 

Si tu regardes bien, la seule différence entre une interface et une classe abstraite est le fait qu'une interface ne peut pas avoir de membres private. Tous ses membres sont publics. C'est une différence très minime, il n'y a donc aucune raison de distinguer un type abstrait d'un type interface, ça ne fait que rajouter de la confusion visuelle.
C'est d'autant plus vrai en Java que ce langage possède des mots clés explicites pour différencier si on implémente une interface ou si on hérite d'une classe : implements et extends, rendant cette distinction encore moins pertinente.
A la rigueur, en C#, le "I" pourrait s'expliquer car l'implémentation ou l'héritage ne sont pas distingués (on utilise ":" dans les deux cas).
Tous les IDE permettent de distinguer une interface en plaçant une icône devant leur définition (géneralement un "I" entouré).
De plus, il se pose un problème ergonomique : si tu recherches un nom de classe dans ton IDE, la partie la plus significative de ta recherche est le début de ta chaine. En préfixant tes interfaces (par "I" par exemple), tu vas avoir tout un paquet de chaines qui commencent par "I", mais qui sont néanmoins similaires, ce qui rendra leur distinction plus difficile.


---------------
J'ai un string dans l'array (Paris Hilton)

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Java

  Polymorphisme et intérêt des interfaces

 

Sujets relatifs
Polymorphisme et static_castinteret de l'ecriture hexadecimale
Javascript - de l'intérêt de la compression[JEE] Passer d'interfaces distantes à locales
Intêret de nusoapquestion d'héritage et polymorphisme
Difficulté à comprendre les CMSintéret du typage
Clustering et load balancing : c'est quoi l'intérêt ?Lister les interfaces réseau physiques
Plus de sujets relatifs à : Polymorphisme et intérêt des interfaces



Copyright © 1997-2016 Hardware.fr SARL (Signaler un contenu illicite) / Groupe LDLC / Shop HFR