Classe abstraite implémentant une interface - C#/.NET managed - Programmation
Marsh Posté le 07-11-2006 à 10:15:00
Questions de vocabulaire:
-qu'est-ce qu'une classe abstraite ?
-qu'est-ce qu'une interface ?
-qu'est-ce qu'une implémentation ?
Marsh Posté le 07-11-2006 à 10:27:06
Une classe abstraite représente de manière incomplète la définition d'un objet. Permet de définir des données et des méthodes concrètes.
Une interface présente une définition de méthodes. La partie publique d'une ou plusieurs classes concrètes en général.
Une implémentation c'est simplement se conformer à la définition d'une interface.
Oui mais pourquoi ne pas déléguer l'implémentation des méthodes de l'interface vers la première classe concrète et non la classe qui implémente directement l'interface ?
Marsh Posté le 07-11-2006 à 10:34:32
Bah si tu veux faire ça, tu dois faire de l'héritage multiple: ta classe concrète devrait hériter à la fois de la classe abstraite, puis de l'interface.
Si tu désignes ta classe comme implémentant une interface, alors elle doit... l'implémenter non ?
Marsh Posté le 07-11-2006 à 10:41:54
_darkalt3_ a écrit : Si tu désignes ta classe comme implémentant une interface, alors elle doit... l'implémenter non ? |
Oui c'est juste, mais mon cas est un peu absurde car dans ma classe abstraite (B), toutes les méthodes de l'interface (IA) seront définit comme 'abstraites' . Donc on ne peut pas vraiment dire que la classe B implémente l'interface IA .
EDIT: juste en passant, l'héritage multiple n'existe pas en C#
Marsh Posté le 07-11-2006 à 10:45:17
Ummon a écrit : Oui c'est juste, mais mon cas est un peu absurde car dans ma classe abstraite (B), toutes les méthodes de l'interface (IA) seront définit comme 'abstraites' . Donc on ne peut pas vraiment dire que la classe B implémente l'interface IA . |
Donc je dirais qu'il s'agit d'un souci de design plus que technique.
Ummon a écrit : EDIT: juste en passant, l'héritage multiple n'existe pas en C# |
C# supporte l'héritage multiple d'interfaces, mais pas de classes.
Marsh Posté le 07-11-2006 à 10:47:10
Ummon a écrit : Apparemment toutes les méthodes de l'interface IA doivent être définis dans B. Pourquoi cette obligation ? |
Parce qu'une interface est un contrat, et que c'est le rôle du contrat de vérifier que toutes les classes implémentant une interface implémentent bien l'intégralité de celle ci, une interface est atomique point barre
Ummon a écrit : Oui c'est juste, mais mon cas est un peu absurde car dans ma classe abstraite (B), toutes les méthodes de l'interface (IA) seront définit comme 'abstraites' . Donc on ne peut pas vraiment dire que la classe B implémente l'interface IA . |
Elle forcera toutes ses classes dérivées à les implémenter, donc ça revient au même
Marsh Posté le 07-11-2006 à 10:54:06
masklinn a écrit : Parce qu'une interface est un contrat, et que c'est le rôle du contrat de vérifier que toutes les classes implémentant une interface implémentent bien l'intégralité de celle ci, une interface est atomique point barre |
Oui mais pourquoi ne pas dire : "[..] c'est le rôle du contrat de vérifier que toutes les classes concrètes implémentant une interface [..]" ?
Bon en tout cas merci pour vos réponses.
Marsh Posté le 07-11-2006 à 11:36:03
Ummon a écrit : Oui mais pourquoi ne pas dire : "[..] c'est le rôle du contrat de vérifier que toutes les classes concrètes implémentant une interface [..]" ? |
Parce que la classe abstraite doit également satisfaire les contraintes de l'interface.
Par exemple imaginons qu'on ait une interface Comparable demandant à ce que soit défini l'opérateur "<=>" (on va dire que la définition d'opérateurs se fait comme la définition de fonctions, mais en mettant l'op entre crochets)
Maintenant considérons que nous voulons implémenter des nombres. On va donc créer une classe abstraite Number dont vont hériter les classes Integer et Float:
Code :
|
Code :
|
Code :
|
Bien maintenant on va créer une fonction qui peut prendre deux nombres quelconques et les comparer
Code :
|
Ce code est-il valide? Non, parce que Float et Integer ont beau définir l'opérateur "<=>", celui-ci n'est pas défini sur Number, il ne fait donc pas partie de la représentation du type (de haut niveau) "Number", donc Number ne remplit pas le contrat demandé par Comparable, donc Number n'implémente pas correctement Comparable
Marsh Posté le 07-11-2006 à 12:04:28
Ta méthode "int [<=>](Float a)" ne devrait pas être plutôt "int [<=>](Comparable a)" ?
Vu que tu ne manipules que des objets concrets (via une interface ou une classe abstraite), les définitions de l'interface seront alors forcément implémentées et donc ce cas :
Code :
|
Fonctionne très bien : une des méthodes "Float.[<=>]" ou "Integer.[<=>]" de 'a' sera appelée en passant b en tant que 'Comparable'. Le choix de la méthode dépend du type concret de 'a'.
Marsh Posté le 07-11-2006 à 12:41:43
Ummon a écrit : Ta méthode "int [<=>](Float a)" ne devrait pas être plutôt "int [<=>](Comparable a)" ? |
Bien sûr que non, la comparaison d'un Float n'est définie qu'avec un autre Float, sinon on pourrait comparer un String (qui peut parfaitement implémenter Comparable) à un float, ce qui n'a aucun sens. L'autre possibilité étant de créer la méthode à un plus haut niveau en utilsant des generics/templates, mais c'est un autre problème.
Ummon a écrit : Vu que tu ne manipules que des objets concrets (via une interface ou une classe abstraite), les définitions de l'interface seront alors forcément implémentées et donc ce cas :
|
Non, parce qu'à moins de tenter un downcast (ce qui supprime tout l'intérêt de l'interface ou de types hérités) le type vu ici est Number, et dans l'interface du type Number il n'y a pas de Comparable. Le compilo se fout éperdument du type concret planqué en dessous (et c'est tout l'intérêt de l'abstraction et de l'utilisation d'interfaces et de classes abstraites).
Tout ce que le compilo regarde, c'est si Number implémente [<=>], Number n'implémente pas [<=>] donc c'est incorrect.
Marsh Posté le 07-11-2006 à 13:09:45
Dans ce cas je te pose deux questions :
1) Si je déclare [<=>] comme étant abstrait dans la classe 'Number' alors ton code fonctionne quand même, bien qu'il n'y ait pas réellement de code dans la classe abstraite.
2) Que se passe t'il si je donne à ton 'compare(Number a, Number b)' un Float et un Integer ?
Laisse moi deux minutes pour faire quelques tests concrets
Marsh Posté le 07-11-2006 à 14:35:56
Ummon a écrit : Dans ce cas je te pose deux questions : |
Ce n'est pas un problème de code (d'implémentation), c'est un problème de types (d'interfaces)
Ummon a écrit : 2) Que se passe t'il si je donne à ton 'compare(Number a, Number b)' un Float et un Integer ? |
Ca va dépendre de la gestion de la promotion/coercion dans le langage.
En l'état actuel, une type error
Marsh Posté le 07-11-2006 à 15:46:45
Bon bref, je n'ai toujours pas compris pourquoi il fallait redéfinir les méthodes de l'interface dans la classe abstraite.
Je veux dire par là que définir une méthode de l'interface dans la classe abstraite comme étant abstraite ou ne rien définir du tout revient au même... il faudra l'implémenter dans un classe sous-jacente à la classe abstraite.
J'espère que c'est clair
Marsh Posté le 07-11-2006 à 19:17:10
_darkalt3_ a écrit : Bah si tu veux faire ça, tu dois faire de l'héritage multiple: ta classe concrète devrait hériter à la fois de la classe abstraite, puis de l'interface. |
l'héritage multiple n'existe pas en .NET
Marsh Posté le 07-11-2006 à 19:20:53
Ummon a écrit : Bon bref, je n'ai toujours pas compris pourquoi il fallait redéfinir les méthodes de l'interface dans la classe abstraite. |
pourquoi tu dois implémenté toutes les méthodes d'une interface. ça me parrait parfaitement clair. Une interface sert simplement à mettre un niveau d'abraction au niveau de certains méthodes. Maintenant la façon dont on les implémentes peut varié.
Par exemple, je créer une interface datasource avec x méthodes.
Ensuite je vais créer deux classes implémentant l'interface. L'une qui fait des accès via des Web Services, et la second qui accède directement à la base de données.
Ainsi les classes UI au dessus exploitant un objet implémentant datasource, peuvent être certain que quelque soit l'implémentation de l'objet implémentant l'interface, celles-ci pourront fonctionner de la même façon sans changer quoi que ce soit.
CQFD en ce qui me concerne.
Marsh Posté le 07-11-2006 à 22:18:32
>moi23372
Euh... je repose ma question, ca visiblement tu ne l'as pas lu jusqu'au bout .
Pourquoi est-ce obligatoire de définir toutes les méthodes d'une interface dans une classe abstraite l'implémentant en sachant qu'il y aura forcément une classe concrète au final ?
Pour donner un exemple : I est mon interface, A ma classe Abstraite qui implémente I et C ma classe concrète qui hérite de A.
La question qui tue : Pourquoi ne peut-on pas définir les méthodes de I directement dans C sans les définir dans A ? Si je veux le faire actuellement je dois définir toutes les méthodes de I dans A comme étant abstraites, ce qui me parrait lourd.
Ma question n'est pas très compliquée..
Marsh Posté le 07-11-2006 à 23:03:38
Ummon a écrit : Pourquoi ne peut-on pas définir les méthodes de I directement dans C sans les définir dans A ? |
1. Parce que ça a été implémenté comme ça
2. Parce que ça demanderait un boulot inutile au niveau du compilo
3. Parce que ça n'a strictement aucun intérêt, il y a des choses bien plus lourdes que ça aussi bien en C# qu'en Java
Ummon a écrit : ce qui me parrait lourd. |
Pauvre biquet...
Marsh Posté le 08-11-2006 à 09:05:35
moi23372 a écrit : l'héritage multiple n'existe pas en .NET |
je répète:
_darkalt3_ a écrit : C# supporte l'héritage multiple d'interfaces, mais pas de classes |
Marsh Posté le 08-11-2006 à 09:06:10
masklinn a écrit : 1. Parce que ça a été implémenté comme ça |
Ah voila, je savais que la réponse allait être : "Parce que!"
masklinn a écrit : 2. Parce que ça demanderait un boulot inutile au niveau du compilo |
Pauvre compilateur.
masklinn a écrit : 3. Parce que ça n'a strictement aucun intérêt[..] |
Il me semble que ça a un intérêt, ça peut permettre d'alléger un peu le code dans certaine situation, mais c'est vrai que ce n'est pas primordial.
masklinn a écrit : il y a des choses bien plus lourdes que ça aussi bien en C# qu'en Java |
Certes certes, mais là on s'égare par rapport au sujet.
masklinn a écrit : Pauvre biquet... |
Une mauvaise passe ? Tu veux qu'on en parle Bob ?
Marsh Posté le 08-11-2006 à 09:43:25
Ummon a écrit : Il me semble que ça a un intérêt, ça peut permettre d'alléger un peu le code dans certaine situation, mais c'est vrai que ce n'est pas primordial. |
L'implémentation d'une inférence de type rendrait le code des ordres de magnitude plus léger et serait largement plus utile sur le long terme
Marsh Posté le 08-11-2006 à 12:45:32
Je ne sais pas si tu verra un jour de l'inférence de type en C#. Mais tu dois certainement avoir raison
Marsh Posté le 08-11-2006 à 19:47:07
_darkalt3_ a écrit : je répète: |
J'appele pas ça héritage moi quand on implémente une interface. Tu as sensiblement un problème de vocabulaire...
On hérite d'une autre classe
Mais on implémente une ou plusieurs interface.
Donc pour moi ça coule de source qu'on peut implémenter n interface dans un objet...
Question de vocabulaire, perso je ne suis pas d'accord avec le tiens...
Marsh Posté le 08-11-2006 à 22:05:11
moi23372 a écrit : J'appele pas ça héritage moi quand on implémente une interface. Tu as sensiblement un problème de vocabulaire... |
Ca n'a pas une grosse différence, implémenter une interface est équivalent à hériter d'une classe abstraite pure (classe abstraite ne comportant que des méthodes abstraites), et c'est d'ailleurs comme ça que c'est implémenté en Java (les messages lorsqu'une classe ne réimplémente pas les méthodes abstraites de la classe abstraite dont elle hérite et lorsqu'elle n'implémente pas les méthodes d'une de ses interfaces sont strictement les mêmes), et c'est également comme ça qu'on gère la chose en C++.
On hérite d'une interface en fait, tout simplement, et dans les deux cas.
Ce qui s'oppose à l'héritage de l'interface et de l'implémentation de la MI classique, et à l'héritage d'implémentation des mixins.
Marsh Posté le 09-11-2006 à 09:23:09
moi23372 a écrit : J'appele pas ça héritage moi quand on implémente une interface. Tu as sensiblement un problème de vocabulaire... |
masklinn a écrit : Ca n'a pas une grosse différence, implémenter une interface est équivalent à hériter d'une classe abstraite pure (classe abstraite ne comportant que des méthodes abstraites), et c'est d'ailleurs comme ça que c'est implémenté en Java (les messages lorsqu'une classe ne réimplémente pas les méthodes abstraites de la classe abstraite dont elle hérite et lorsqu'elle n'implémente pas les méthodes d'une de ses interfaces sont strictement les mêmes), et c'est également comme ça qu'on gère la chose en C++. |
Je n'aurais pas mieux dit que Masklinn
Marsh Posté le 09-11-2006 à 20:18:56
masklinn a écrit : Ca n'a pas une grosse différence, implémenter une interface est équivalent à hériter d'une classe abstraite pure (classe abstraite ne comportant que des méthodes abstraites), et c'est d'ailleurs comme ça que c'est implémenté en Java (les messages lorsqu'une classe ne réimplémente pas les méthodes abstraites de la classe abstraite dont elle hérite et lorsqu'elle n'implémente pas les méthodes d'une de ses interfaces sont strictement les mêmes), et c'est également comme ça qu'on gère la chose en C++. |
je ne suis pas d'accord avec toi... Je suis d'accord sur le principe ça en renvient au même... mais bon, tâchons d'employer les termes appropriés pour chaque notion...
Marsh Posté le 09-11-2006 à 22:16:50
moi23372 a écrit : je ne suis pas d'accord avec toi... Je suis d'accord sur le principe ça en renvient au même... mais bon, tâchons d'employer les termes appropriés pour chaque notion... |
Quels termes appropriés? La notion d'interface en tant qu'unité concrète ne fait pas partie de la POO, ni de la théorie des types, c'est quelque chose de spécifique à Java et aux langages qui s'en inspirent (C#, PHP, ...), et dont les designers ont eu besoin quand ils se sont rendu compte d'un problème majeur que posait l'absence de MI dans un langage reprenant les paradigmes du C (càd l'impossibilité qu'un objet ait plusieurs types)
Marsh Posté le 10-11-2006 à 21:47:23
excuse moi, mais php n'a rien avoir avec JAVA, ni avec C#... mais alors ça n'a vraiment aucun rapport. ça ne fonctionne même pas de la façon...
mais vous pouvez persisté dans vos déclarations, vous ne me convainquerez pas... une implémente une interface un point c'est tout... on en dérive pas...
Marsh Posté le 10-11-2006 à 22:02:30
moi23372 a écrit : excuse moi, mais php n'a rien avoir avec JAVA, ni avec C#... mais alors ça n'a vraiment aucun rapport. ça ne fonctionne même pas de la façon... |
Raté, l'espèce de résidu de fausse couche de POO de PHP5 a été tirée directement de celle de Java, avec quelques additions mais ça reste fondamentalement la vision Java de la POO, et le Java est l'un des premiers langages (et le premier un tant soit peu "mainstream" ) à avoir implémenté des interfaces directement dans le langage pour implémenter des ADT, essaie encore.
Marsh Posté le 11-11-2006 à 10:16:54
le jour ou php aura besoin d'une couche tel que la JVM ou le .NET framework signale le moi...
De plus, php est un language interprété, alors que JAVA et .NET sont des architectures compilées...
alors je veux bien qu'éventuellement al nouvelle versoin de php5 a essayué de faire comme tt le monde, mais à la base ça n'a rien avoir du tout... essaie encore
Marsh Posté le 11-11-2006 à 11:59:43
moi23372 a écrit : le jour ou php aura besoin d'une couche tel que la JVM ou le .NET framework signale le moi... |
T'as vraiment du mal avec la lecture toi...
Quand j'ai parlé des langages s'inspirant de Java, c'était au niveau de la couche OO, c'était pourtant relativement clair
Quand au compilé/interprété, Java comme .Net sont des archis interprétée, pas uniquement compilées
Marsh Posté le 14-11-2006 à 18:12:11
moi23372 a écrit : le jour ou php aura besoin d'une couche tel que la JVM ou le .NET framework signale le moi... |
En même temps, le moteur Zend s'apparente pas mal à une VM...
Marsh Posté le 21-11-2006 à 16:50:49
masklinn a écrit : Ca n'a pas une grosse différence, implémenter une interface est équivalent à hériter d'une classe abstraite pure (classe abstraite ne comportant que des méthodes abstraites) |
Oui et non.
Tout est une question de point de vue.
Au début je voyais aussi les choses comme ça, mais de moins en moins.
Perso, implémenter une interface c'est comme donner un nouvel aspect à un objet (mais je suis pas spécialiste de la programmation par aspects), une façon de le voir.
Autant l'héritage est formellement hiérarchique et permet de "classer" les objets par nature imbriquées.
Autant les interface sont une classification transversale, par nature non hiérarchique.
Pour preuve : "Type.GetInterfaces" retourne toutes les interfaces implémentées par la classe et toutes ses super-classes, dans un ordre connu de lui seul.
La hiérarchie ? Inconnue. pour la trouver, il faut beaucoup jouer avec la Reflection. Et encore, ça marche pas à tous les coups.
P.S. : j'ai pas mal joué avec les interfaces et la Reflection avec le fx1.1, mais j'ai pas encore checké en fx2.0, si qqn peut confirmer/infirmer.
Marsh Posté le 21-11-2006 à 16:58:38
_Mose_ a écrit : Perso, implémenter une interface c'est comme donner un nouvel aspect à un objet (mais je suis pas spécialiste de la programmation par aspects), une façon de le voir. |
Je dirais plutot qu'un interface donne une capacité à à une classe, pour relancer de un.
Marsh Posté le 21-11-2006 à 19:45:06
Ah bah non !
Imagine que je créé INamed, l'interface des objets nommés (avec une propriété Name)
Puis je demande à ma Form1 de l'implémenter, je n'ajoute rien.
La propriété Name existait déjà avant
En revanche, ma Form1 a maintenant l'aspect d'un objet nommé (on peut la caster en INamed)
Enfin sinon dans le fond on s'en fout, c'est pareil :
Un outil qui a l'aspect d'une clef, tu peux le tourner.
Une clef, c'est un outil qui a la capacité de tourner...
Bon aller, on va dire qu'une interface donne un aspect à un objet auquel elle rajoute ou pas des capacités
Marsh Posté le 21-11-2006 à 19:52:27
moi23372 a écrit : le jour ou php aura besoin d'une couche tel que la JVM ou le .NET framework signale le moi... |
Le PHP est compilé en bytecode au même titre que Java ou .Net Des truc genre Zend platform ou APC existent pour garder une version pseudo-compilée des scripts
Marsh Posté le 07-11-2006 à 10:13:01
Bonjour,
Voila, c'est tout simple :
J'ai un classe abstraite B qui implémente l'interface IA.
Apparemment toutes les méthodes de l'interface IA doivent être définis dans B. Pourquoi cette obligation ?
Je vous avez dit que c'était simple