Salut,
Tout est dit dans le titre;
je comprend l'heritage mais je n'arrive pas a comprendre
le polymorphisme;
est ce que quelqu un pourrait me l' expliquer avec un exemple
merci de votre aide
Salut,
Tout est dit dans le titre;
je comprend l'heritage mais je n'arrive pas a comprendre
le polymorphisme;
est ce que quelqu un pourrait me l' expliquer avec un exemple
merci de votre aide
Ta question est paradoxale puisque "héritage" et "polymorphisme" sont liés, si tu ne comprends pas l'un, tu ne peux pas comprendre l'autre.
Ou plus exactement "héritage" et "polymorphisme d'inclusion" sont liés.
En effet il y a plusieurs types de polymorphismes, on en recense trois principaux :
- polymorphisme d'inclusion, comme je l'indiquais ce type est lié à l'héritage et plus exactement au sous-typage (ordre sur les types), il s'agit d'utiliser comme argument un objet de classe B qui hérite de la classe A à la place d'un objet de la classe A. Il y a des subtilités (cf. variance et contravariance).
- polymorphisme ad-hoc : autrement appelé "surcharge" il s'agit de donner plusieurs signatures (type) à un même symbole, comme << en C++ où selon ses arguments il représente un décalage de bits ou une opération d'E/S. Comme l'indique le ad-hoc il n'y a pas forcément de relation entre les divers types et actions associées à un même symbole (opérateur ou fonction).
- polymorphisme paramétrique : c'est ce qu'on retrouve sous l'appellation "génériques" en Java par exemple (ou dans les templates en C++). Il s'agit d'une opération qui ne touche pas vraiment aux contenus des données qu'on lui donne et qu'on peut donc utiliser avec des données de n'importe quel type. Un exemple simple serait le combinateur K qui renvoie son premier argument : "K a b = a". K ne touche pas au contenu de a et b donc ces arguments peuvent être d'un type quelconque, en Java on écrirait quelque chose comme :
Code Java : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 A K<A, B>(A a, B b) { return a; }
Est-ce un peu plus clair pour toi ? (Ou encore plus embrouillé ? )
N'hésite pas à demander des précisions.
--
Jedaï
Si tu te demandes toujours ce qu'est la différence entre héritage et polymorphisme d'inclusion (j'appellerais ça PI à l'avenir), il faut bien te dire que le PI est une notion plus vaste que l'héritage : l'héritage n'est qu'une des façon d'implémenter le sous-typage dans le contexte restreint des langages à classes. Il existe d'autres types de langages où on peut retrouver du sous-typage sans héritage, par exemple dans les langages à prototypes avec du duck-typing (discipline de typage qui regarde les capacités respectives de deux objets plutôt que leur classe pour décider si l'un peut être utilisé ou renvoyé à la place de l'autre).
--
Jedaï
Que tu roules avec une clio, une 207 ou une autre voiture en général, tu peux executer les mêmes actions, elles présentent des comportements identiques, ou plutôt elles ont toutes un tableau de bord avec des commandes et un volant.
Quand tu passes le permis de conduire, tu peux conduire une voiture (n'importe quelle voiture), en pratique c'est un modèle de voiture. En POO, on parle de polymorphisme.
Est-ce que cet exemple te parles ?
Oups: quelqu'un a répondu, du coup mon exemple va être puéril.
Si je puis me permettre, pourrais-t-on m'expliquer en des termes simples la (co?)variance et la contravariance (j'ai lu cet article, mais je reste sur ma fin).
Plus j'apprends, et plus je mesure mon ignorance (philou67430)
Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
Si c'est utile, say
Voyons, la covariance et la contravariance...
Si on a un ordre sur les types, on dit que A < B si le type A est plus spécifique que le type B (exemple, la classe A hérite de la classe B), le type A peut alors être utilisé comme argument de toute fonction qui pouvait prendre du B parce que A sait faire tout ce que sait faire B (et éventuellement plus).
On dit d'un opérateur de type T() qu'il est :
- covariant si A < B ==> T(A) < T(B)
- contravariant si A < B ==> T(A) > T(B)
- invariant si aucunes de ces deux implications n'est vraie.
L'exemple classique est la fonction.
Soit C un type quelconque,
Soit Arg() l'opérateur de type tel que Arg(x) = x -> C (fonction de x vers C)
Soit Res() l'opérateur de type tel que Res(x) = C -> x.
Alors Arg() est contravariant car A < B ==> Arg(B) < Arg(A) :
On peut utiliser une fonction qui prend B en argument partout où l'on pouvait utiliser une fonction qui prend A en argument.
Et Res() est covariant.
--
Jedaï
C'est notamment le cas des langages à typage dynamique, tel que Ruby. Le terme de « polymorphisme » est d'ailleurs totalement absent de la littérature consacrée à ce langage (enfin, du moins de tout ce que j'ai pu lire) au profit du « duck-typing » (si ça marche comme un canard et si ça fait « coin-coin » comme un canard, alors c'est un canard).
FAQ XML
------------
« Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser »
Giacomo Leopardi
C'est l'exemple le plus commun en effet, mais à vrai dire j'ai un peu hésité à le citer puisque parler de sous-typage lorsqu'il n'y a pas de type (statique en tout cas) est un peu bizarre. Néanmoins on peut également retrouver ce principe du duck-typing dans des langages typés statiquement, comme en OCaml ou en F# et dans ces cas, parler de sous-typage et de polymorphisme d'inclusion est incontestable.
--
Jedaï
Excellente réponse d'expert Les débutants en POO sont très sensibles à l'utilisation d'un vocabulaire élémentaire et sont très perturbés par les réponses qui embrassent plus large que la question immédiate qui les occupe. De plus, à cause du paradigme, la plupart des programmeurs POO pensent dynamiquement plutôt que statiquement, ils pensent 'objets' plutôt que 'classes' et ils pensent 'classes' plutôt que 'types'. La notion de type est celle qui les perturbe le plus. Une réponse qui se rapporte à "ce diagramme commute" ne fait pas écho parce que les types ne sont pas considérés comme un cadre structurant la conception mais plutôt comme une discipline imposée par le compilateur pour des raisons de sécurité et/ou d'efficacité.Envoyé par Jedai
Dans la littérature POO polymorphisme signifie polymorphisme d'inclusion.Envoyé par Melvine
Un nouveau type-classe a deux visages.
Vu de l'implémenteur c'est une nouvelle classe (ce qu'on appelle aussi parfois une boîte blanche).
Vu de l'utilisateur c'est un nouveau type (ce qu'on appelle aussi parfois une boîte noire).
Il existe une hiérarchie entre les boîtes.
Les boîtes blanches sont hiérarchisées par une relation d'héritage.
Les boîtes noires sont hiérarchisées par une relation de compatibilité.
Statiquement: le polymorphisme c'est le fait que toute relation d'héritage entre deux boîtes blanches entraine aussi une relation de compatibilité entre les deux boîtes noires. Ou bien, dit autrement, c'est le fait qu'une classe implante à la fois un type et son super-type.
Dynamiquement: le polymorphisme c'est le fait que les commandes deviennent des invocations (un ordre dont l'exécution est modulable suivant le contexte) plutôt que des injonctions (un ordre dont l'exécution est prescrite). Ou bien, dit autrement, c'est le fait qu'un objet d'une certaine classe est également un objet de la super-classe.
Du même auteur: mon projet, le dernier article publié, le blog dvp et le jeu vidéo.
Avant de poser une question je lis les règles du forum.
Bonjour,
Au sujet du polymorphisme, je me permets de soumettre le lien vers un post auquel j'ai répondu sur le forum Java, dans lequel la personne s'interrogeait sur la différence entre écrireet
Code : Sélectionner tout - Visualiser dans une fenêtre à part superclasse mareference = new sousclasse () ;et où je donne quelques exemples simples : http://www.developpez.net/forums/d76...ion-lheritage/. En espérant que cela t'éclaire, Melvine .
Code : Sélectionner tout - Visualiser dans une fenêtre à part sousclasse mareference = new sousclasse () ;
Merci Jedaï et SpiceGuid.
J'essaye de re-formuler la contravariance avec mes mots : la contravariance, c'est lorsque le comportement des types est inverse au comportement des classes lors d'une transformation de type. C'est à dire, par exemple, que si l'on passe en paramètre à une méthode un objet de type A là où l'on attends un objet de type B (avec A < B), dans la méthode, l'objet pris en argument se comportera comme un objet de type A, c'est à dire plus spécialisé que le type B de l'argument attendu réellement (à savoir qu'un méthode redéfinie dans la classe B sera utilisée en lieu et place de celle de A) ?
Corolaire : le comportement de C++ et de Java est-il identique du point de vue de la variance des opérateurs de type ?
Plus j'apprends, et plus je mesure mon ignorance (philou67430)
Toute technologie suffisamment avancée est indiscernable d'un script Perl (Llama book)
Partagez vos problèmes pour que l'on partage ensemble nos solutions : je ne réponds pas aux questions techniques par message privé
Si c'est utile, say
si tu veux un exemple plus concret
http://jlambert.developpez.com/tutor...scsharp4/#L3-6
Quand tu passe un paramètre réel ça n'a aucun rapport avec la variance, la variance d'un paramètre c'est toujours la variance d'un paramètre formel.Envoyé par Philou67430
Dans le cas de l'article cité par gorgonite il s'agit de variance de paramètre générique formel. Chaque fois que vous parlez de paramètre (argument d'une fonction) ou de générique (argument d'un type) essayez de préciser réel ou formel, sinon vous allez rapidement vous embrouiller ou embrouiller le lecteur (ça vaut pour les rédacteurs d'articles).
Du même auteur: mon projet, le dernier article publié, le blog dvp et le jeu vidéo.
Avant de poser une question je lis les règles du forum.
Salut
Je vais y aller de ma petite réponse. Je m'en excuse d'avance, je sens que je vais dériver dans du nettement trop théorique
Vu qu'on veut parler de sous-typage, parlons d'abord de typage ! Qu'est ce qu'un type ? Je pense qu'il y a plusieurs façons de voir ce qu'est un type, mais en gros, on peut voir un type comme un ensemble de valeur.
Cet ensemble peut être défini de façon assez ad-hoc, par exemple sur la représentation mémoire. Ca va typiquement être le cas du type "entier". Un int, c'est un valeur représentable sur un mot machine, et sur laquelle on peut faire un certain nombre d'opération.
Pour les types plus intéressant, cet ensemble de valeurs est défini par un propriété. (L'axiome de compréhension de la théorie des ensemble nous dit qu'une propriété définie bien un ensemble). Par exemple l'ensemble des fonction de int vers float c'est "l'ensemble des fonction qui, lorsqu'elles reçoivent en argument un entier, soit ne termine pas, soit retourne un flottant". Dans la suite, on notera int -> float le type d'une telle fonction.
Maintenant, qu'est ce que le type d'un objet ? Théoriquement, le type d'un objet, c'est celui de l'interface qu'il présente au monde (on verra que ce n'est pas exactement comme ça dans les langages que C++ et Java, mais je trouve que c'est quand même une approche plus claire)
Donc par exemple un objet voiture qui saurait accélérer, tourner et donner sa position devrait avoir une signature du genre : (unit, c'est en gros comme void en java ou autre)
Disons que j'ai aussi une fonction guider qui attend en entrée une voiture et un position objectif, et qui guide la voiture jusqu'à la position, en relevant d'abord ça position initiale, puis en jouant sur les accélération et rotation:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 type voiture = <accelerer : float -> unit; tourner : float -> unit; position : unit -> (float, float)>
Maintenant pour une raison quelconque, j'ai besoin de créer une voiture décapotable, qui sait faire les même choses qu'une voiture normale, mais aussi se décapoter :
Code : Sélectionner tout - Visualiser dans une fenêtre à part guider : (voiture, (float, float)) -> unit
Sans sous typage, on ne peux pas utiliser la fonction guider sur une voiture_decap, puisqu'elle n'a pas exactement le type voiture attendu, mais une méthode de plus ! Il faudrait donc réécrire une fonction guider_decap qui aurait exactement le même code, mais qui aurait pour type
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 type voiture_decap = <accelerer : float -> unit; tourner : float -> unit; position : unit -> (float, float) decapoter : unit -> unit>
Pourquoi le code serait-il exactement le même ? Tout simplement parce que là où une voiture normale peut être utilisée, une voiture décapotable peut tout aussi bien être utilisée. C'est en fait ça la définition du sous typage. Un type A est un sous type de B si partout où un élément de type B est attendu, un de type A peut être utilisé. Et dans le monde objet, "pouvoir être utilisé à la place de", ça se résume globalement à "avoir au moins les méthode de". Une voiture_decap a bien toutes les méthodes d'une voiture et peut donc être utilisé à la place.
Code : Sélectionner tout - Visualiser dans une fenêtre à part guider_decap : (voiture_decap, (float, float)) -> unit
Dans une vision ensembliste, un type A est un sous type de B s'il est inclus dedans.
Maintenant quid de l'héritage ? L'héritage a pour but de récupérer les fonctionnalités de la classe mère, bref, le code de ses méthodes. Après, qui dit récupération du code des méthodes dit aussi récupération de leur type, et donc dans le cas général, héritage implique sous typage. Mais il faut bien comprendre qu'il n'y a aucune raison de limiter le sous typage à l'héritage. C'est d'ailleurs ce que java fait avec la notion d'interface et C++ avec les classes virtuelles, mais de façons assez pauvre. Le modèle objet d'OCaml est bien plus fun à ce niveau
Je reviens sur les problèmes de co et contra variance plus tard
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager