Partage
  • Partager sur Facebook
  • Partager sur Twitter

Héritage, classes abstraites et interfaces

Sujet résolu
    23 mars 2009 à 11:46:17

    Bonjour,
    J'aimerais bien que quelqu'un me donne un petit exercice a faire en java et ensuite le corriger, où j'aurais besoin des ces trois la citer et qui sont indispensable, car je ne sais toujours pas a quoi elles serviront pour le moment :-° .
    Même si je sais que, l'héritage c'est pour hériter de tout les méthodes de son père, classes abstraites ne peuvent être instanciée et les interfaces 100% abstraites ...

    Merci cordialement
    • Partager sur Facebook
    • Partager sur Twitter
      23 mars 2009 à 12:02:32

      Voila quelques listes d'exo ici, et re ici.
      Si besoin de plus demandes à ton moteur de recherche préféré.
      • Partager sur Facebook
      • Partager sur Twitter
        23 mars 2009 à 12:43:24

        Merci je vais essayer quelques-un :D
        • Partager sur Facebook
        • Partager sur Twitter
        Anonyme
          23 mars 2009 à 12:51:53

          Citation : SoftDeath

          Même si je sais que, l'héritage c'est pour hériter de tout les méthodes de son père, classes abstraites ne peuvent être instanciée



          Ca va un peu plus loin que ça, une relation parent enfant est une relation "is a", c'est a dire que tout enfant doit avoir un comportement en adéquation avec l'implémentation de la classe parent, ce comportement peut soit être étendu par certaines fonctionnalités ajoutés, soit redéfinir les fonctionnalités existantes (soit ne rien faire du tout, ça arrive parfois, pour utiliser le type en introspection par exemple).

          Une interface est par contre une relation "can do", un contrat entre l'interface et l'implémentation qui dit que la classe sera capable d'effectuer les actions définies(a condition que la classe soit concrète, bien sur).

          NB: en java on peut instancier directement les interfaces et classes abstraites en leur fournissant une implémentation à la volée(anonymous inner class).
          • Partager sur Facebook
          • Partager sur Twitter
            24 mars 2009 à 1:09:17

            Bonjour,

            Citation : shakhal

            Ca va un peu plus loin que ça, une relation parent enfant est une relation "is a", c'est a dire que tout enfant doit avoir un comportement en adéquation avec l'implémentation de la classe parent


            Ceci n'est rien d'autre que la relation d'héritage. De par sa nature même, un sous type dispose des mêmes propriétés que son super type), c'est notamment grâce à ceci que la polymorphie est possible.

            Citation : shakhal

            ce comportement peut soit être étendu par certaines fonctionnalités ajoutés, soit redéfinir les fonctionnalités existantes (soit ne rien faire du tout, ça arrive parfois, pour utiliser le type en introspection par exemple).


            Quel rapport avec l'introspection (on dit reflexion en Java) ?
            On peut "tagger" un type via l'implémentation d'une interface, afin de ne pas priver de hierarchie la classe (oui l'héritage multiple n'existe pas en Java). C'est le cas par exemple de Serializable qui ne fait que tagger un type et permet à la JVM de préparer la Serialization. Cependant depuis nous avons les annotations et l'existance même de cette interface n'a plus lieu d'être, mais sun tient a sa retrocompatibilité.

            Citation : shakhal

            Une interface est par contre une relation "can do", un contrat entre l'interface et l'implémentation qui dit que la classe sera capable d'effectuer les actions définies(a condition que la classe soit concrète, bien sur).


            La relation entre une interface et un type est celle de l'héritage. Une interface peut dériver d'une autre (parlerais-tu de can-do dans ce cas ?) Le polymorphisme, la restriction de type dans les generics, la convariance des types de retours, ne font aucunement la distinction entre interface, classe abstraite, et classe concrète. La relation est strictement identique. Si on parle de conception on pourrait diverger vers l'utilisation de relation is-a ou has-a, mais ce n'est absolument pas le sujet.

            Citation : shakhal

            NB: en java on peut instancier directement les interfaces et classes abstraites en leur fournissant une implémentation à la volée(anonymous inner class).


            Cette instanciation anonyme (qui cela dit en passant n'a rien à voir avec les inner class), revient à créer un sous type de l'interface, et donc une implémentation classique. Les objects anonymes sont toujours évitables, et il est préférable de passer par une classe concrète (le code à usage unique c'est pas top pour la reutilisabilité).

            Pourquoi ne pas laisser notre jeune apprenti apprendre doucement, plutôt que de lui inculquer des notions fausses ?
            • Partager sur Facebook
            • Partager sur Twitter
            Anonyme
              24 mars 2009 à 12:15:14

              Merci de corriger mes lacunes, cependant, il y a certaines choses que je voudrais approfondir:

              Citation : Kazou_


              Ceci n'est rien d'autre que la relation d'héritage. De par sa nature même, un sous type dispose des mêmes propriétés que son super type), c'est notamment grâce à ceci que la polymorphie est possible.



              Les propriétés sont accessibles seulement si la visibilité le permet, cependant, afin de renforcer l'encapsulation, j'estime (et ne suis pas le seul, loin de la) que l'enfant ne doit pas avoir accès aux propriétés de son parent directement, et donc doit seulement hériter de comportements (qui peuvent être des accès aux données dans le cas de classes data bien sur).

              Citation : Kazou_

              Quel rapport avec l'introspection (on dit reflexion en Java) ?



              L'introspection est le terme général pour désigner la capacité du programme à connaître son état, reflexion est plus général et permet également de modifier cet état, dans mon explication, je n'exprimais que le fait de connaitre l'état, d'ou le choix du terme.

              Le rapport est que l'introspection permet de connaitre le type de la sous-classe, celui ci pouvant pouvant donner un comportement différent au programme même si la sous-classe n'a pas d'implémentation propre, tagguer comme tu dis a la différence qu'ici on garde le lien parent enfant pour diverses raisons.

              Pour les annotations, si c'est juste pour tagguer, tu as raison c'est plus sympa, par contre pour le polymorphisme (et donc la relation "can do", ça remplace pas).

              Citation : Kazou_

              La relation entre une interface et un type est celle de l'héritage. Une interface peut dériver d'une autre (parlerais-tu de can-do dans ce cas ?) Le polymorphisme, la restriction de type dans les generics, la convariance des types de retours, ne font aucunement la distinction entre interface, classe abstraite, et classe concrète. La relation est strictement identique. Si on parle de conception on pourrait diverger vers l'utilisation de relation is-a ou has-a, mais ce n'est absolument pas le sujet.



              L'héritage s'applique entre 2 interfaces, mais la relation "can do" s'applique toujours entre l'interface enfant(qui hérite des comportements à implémenter du parent) et l'implémentation.

              La restriction de type dans les generics reste applicable en général, si l'interface ne défini aucun comportement, à implémenter, je vois difficilement l'intérêt de l'utiliser dans un generic (sauf pour du stockage a la rigueur). Vraiment je vois pas a quoi servirait une classe qui ne sait rien faire(et donc sans relation "can do" entre elle et son interface). Si tu as des exemples concrets où tu as déjà du utiliser ça, ça m'intéresse.

              Pour la covariance je pense que c'est évident, en java le type de retour ne fait pas partie de la signature, donc que ce soit dans le cas d'une redéfinition ou d'une implémentation, ça revient strictement au même, la différence se ferait si un type de retour différent signifiait une surcharge.

              Et oui je parlais bien entendu de conception, on peut évidemment faire de l'héritage a toutes les sauces mais autant essayer de donner un bon point de départ aux gens qui commencent (plutôt que le traditionnel "l'héritage c'est pour rassembler le code commun" qui conduit a des abérations sémantiques pas croyables.

              Citation : Kazou_

              Cette instanciation anonyme (qui cela dit en passant n'a rien à voir avec les inner class), revient à créer un sous type de l'interface, et donc une implémentation classique. Les objects anonymes sont toujours évitables, et il est préférable de passer par une classe concrète (le code à usage unique c'est pas top pour la reutilisabilité).



              Une classe qui ne peut exister qu'au sein d'une autre est inner, c'est d'ailleurs le terme utilisé sur le site de sun.

              Il est évident que ça revient à créer une implémentation classique, je n'ai jamais prétendu autre chose, cependant je ne suis pas d'accord du fait que ce soit toujours évitable, si l'implémentation est courte, et qu'elle à besoin des variables utilisées dans la méthode ou l'implémentation est faite, il serait regrettable de devoir passer ces variables en attribut, donc réduire l'encapsulation juste pour implémenter une ou 2 méthodes dans un classe concrète externe.

              un exemple simple avec swt:
              private void initialise() {
              ...
              final Tree tree = new Tree(treeLabelGroup, SWT.SINGLE);
              tree.addMouseListener(new MouseListener() {
              
                          @Override
                          public void mouseDoubleClick(MouseEvent arg0) {
                              client.lcdCommand(tree.getSelection()[0].getText());
                          }
              ...
              }
              


              Voila un cas où, si j'avais voulu utiliser une classe externe, j'aurais du exposer tree, et donc affaiblir mon encapsulation(ou compliquer le code en renvoyant des copies, mais ça ne change pas que tree n'a pas à être vu depuis l'extérieur).
              Et ici bien entendu que le code est a usage unique vu que c'est une ihm, ce n'est pas possible d'avoir 100% de code réutilisable dans une appli (et tant mieux sinon on serait tous au chômage).

              Citation : Kazou_


              Pourquoi ne pas laisser notre jeune apprenti apprendre doucement, plutôt que de lui inculquer des notions fausses ?



              Parce que c'est un forum, qu'il pourra relire ce post quand il comprendra mieux comment ça se passe.
              Pour les notions fausses, je pense que c'est discutable, mais je me fie à ta plus grande expérience.

              Merci de me corriger si mon raisonnement est incorrect.





              • Partager sur Facebook
              • Partager sur Twitter
                24 mars 2009 à 13:05:39

                WAW :waw: ça discute ici, je reposte pour dire que j'ai fais les exos (il me manque un :-° )qu'on m'a donné en lien et je crois (enfin je pensais avant vos postes instructifs :magicien: merci) avoir compris l'héritage les classes abstraites et les interfaces :) .
                Cordialement
                • Partager sur Facebook
                • Partager sur Twitter
                  24 mars 2009 à 15:16:18

                  Bonjour,

                  Citation : shakhal

                  Les propriétés sont accessibles seulement si la visibilité le permet, cependant, afin de renforcer l'encapsulation, j'estime (et ne suis pas le seul, loin de la) que l'enfant ne doit pas avoir accès aux propriétés de son parent directement, et donc doit seulement hériter de comportements (qui peuvent être des accès aux données dans le cas de classes data bien sur).



                  Toute méthode surchargé doit être publique ou protected, une private ne pourra jamais être overrider. Cependannt je suis de ton avis sur le point où accéder à des attributs directement(aussi bien de l'exterieur que depuis la sous-hierarchie), est une pratique dangereuse qui peut conduite à un plantage.

                  Citation : shakhal


                  Le rapport est que l'introspection permet de connaitre le type de la sous-classe, celui ci pouvant pouvant donner un comportement différent au programme même si la sous-classe n'a pas d'implémentation propre, tagguer comme tu dis a la différence qu'ici on garde le lien parent enfant pour diverses raisons.


                  Pour les annotations, si c'est juste pour tagguer, tu as raison c'est plus sympa, par contre pour le polymorphisme (et donc la relation "can do", ça remplace pas).



                  Je ne vois pas à quoi peut servir une interface vide si ce n'est que pour tagger un autre type. On pourrait imaginer que l'on puisse s'en servir pour utiliser un meilleur type que Object (notamment pour les conteneurs), mais je ne suis pas convaincu que ca soit très élégant.

                  Citation : shakhal

                  Pour la covariance je pense que c'est évident, en java le type de retour ne fait pas partie de la signature, donc que ce soit dans le cas d'une redéfinition ou d'une implémentation, ça revient strictement au même, la différence se ferait si un type de retour différent signifiait une surcharge.


                  Non, puisque le type de retour ne fait pas partie de la signature, on ne peut prétendre à de la surcharge avec pour seule différence le type de retour. Ce qui permet la convariance des types de retours est bien la relation is-a.

                  Citation : shakhal

                  Et oui je parlais bien entendu de conception, on peut évidemment faire de l'héritage a toutes les sauces mais autant essayer de donner un bon point de départ aux gens qui commencent (plutôt que le traditionnel "l'héritage c'est pour rassembler le code commun" qui conduit a des abérations sémantiques pas croyables.


                  Je suis tout à fait d'accord avec toi sur ce point. L'héritage est "pratique" mais mène à des structères de données rigides et difficiles à maintenir. La composition est beaucoup plus utilisée et bien plus souple (d'ailleurs elle est utilisée dans la plupart des modèles de conceptions).

                  Citation : shakhal

                  Une classe qui ne peut exister qu'au sein d'une autre est inner, c'est d'ailleurs le terme utilisé sur le site de sun.


                  Une inner classe n'est pas forcément utilisée que dans une autre classe (c'est qui est en revanche le cas des locales classes).
                  MyOuter.MyInner = new Outer().new Inner(); // hors classe.
                  


                  Citation : shakhal

                  Il est évident que ça revient à créer une implémentation classique, je n'ai jamais prétendu autre chose, cependant je ne suis pas d'accord du fait que ce soit toujours évitable, si l'implémentation est courte, et qu'elle à besoin des variables utilisées dans la méthode ou l'implémentation est faite, il serait regrettable de devoir passer ces variables en attribut, donc réduire l'encapsulation juste pour implémenter une ou 2 méthodes dans un classe concrète externe.


                  Cela à un prix : les variables accessibles doivent être finales (ce qui n'est pas toujours le cas, et peut être contraignant). Passer une instance en paramètre ne coûte rien (c'est une copie de référence), et l'encapsulation reste réspéctée au travers des accesseurs. Je comprends tout à fait ce que tu resent quand tu dis ça, et c'est justifié, mais ne crois-tu pas qu'il est plus mauvais pour l'encapsulation d'avoir acces à tout, (c'est a dire exposter tout le contenu finale), plutot que de controler ce qui passe au travers d'accesseurs ?

                  Citation : shakhal

                  Et ici bien entendu que le code est a usage unique vu que c'est une ihm, ce n'est pas possible d'avoir 100% de code réutilisable dans une appli (et tant mieux sinon on serait tous au chômage).


                  Techniquement si, mais plutôt difficile à mettre en place. Après il y a ce qui est le top, et ce qui est envisageable. Il y a un équilibre entre les deux. Utiliser trop de pattern est un anti-pattern comme on dit.

                  Citation : shakhal

                  Pour les notions fausses, je pense que c'est discutable, mais je me fie à ta plus grande expérience.


                  C'est en effet discutable. J'ai posté ça quand je devais les avoir à l'envers. Désolé si je fûs un peu agressif.
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Anonyme
                    24 mars 2009 à 17:24:28

                    Citation : Kazou_

                    Bonjour,Toute méthode surchargé doit être publique ou protected, une private ne pourra jamais être overrider. Cependannt je suis de ton avis sur le point où accéder à des attributs directement(aussi bien de l'exterieur que depuis la sous-hierarchie), est une pratique dangereuse qui peut conduite à un plantage.


                    Oui, c'est pour ça que je préconise de n'hériter que du comportement (les méthodes donc) et de bien encapsuler les attributs du parent.

                    Citation : Kazou_

                    Je ne vois pas à quoi peut servir une interface vide si ce n'est que pour tagger un autre type. On pourrait imaginer que l'on puisse s'en servir pour utiliser un meilleur type que Object (notamment pour les conteneurs), mais je ne suis pas convaincu que ca soit très élégant.


                    Moi non plus, j'ai du mal interpréter ton message sans doute, par contre, il arrive (du moins il m'arrive) d'utiliser des classes qui extends une abstract class sans lui ajouter de comportement, c'est utile quand on a besoin de différencier un type tout en gardant la relation "is a" (mais ce sont des cas assez particuliers résultant d'architecture exotique)


                    Citation : Kazou_

                    Non, puisque le type de retour ne fait pas partie de la signature, on ne peut prétendre à de la surcharge avec pour seule différence le type de retour. Ce qui permet la convariance des types de retours est bien la relation is-a.



                    C'est vrai, il serait illogique de modifier le type de retour d'une implémentation, la covariance se résume donc la redéfinition.

                    Citation : Kazou_

                    Je suis tout à fait d'accord avec toi sur ce point. L'héritage est "pratique" mais mène à des structères de données rigides et difficiles à maintenir. La composition est beaucoup plus utilisée et bien plus souple (d'ailleurs elle est utilisée dans la plupart des modèles de conceptions).


                    Tout à fait, pour ma part je n'hérite d'ailleurs jamais de classes concrètes, sauf si les wrapper pose vraiment trop de problèmes.

                    Citation : Kazou_

                    Une inner classe n'est pas forcément utilisée que dans une autre classe (c'est qui est en revanche le cas des locales classes).

                    MyOuter.MyInner = new Outer().new Inner(); // hors classe.
                    




                    En effet j'avais pensé aussi à cet exemple mais son implémentation reste au sein d'une classe, mais j'avoue que j'ai eu (et ai toujours) un doute à ce sujet.


                    Citation : Kazou_

                    Cela à un prix : les variables accessibles doivent être finales (ce qui n'est pas toujours le cas, et peut être contraignant). Passer une instance en paramètre ne coûte rien (c'est une copie de référence), et l'encapsulation reste réspéctée au travers des accesseurs. Je comprends tout à fait ce que tu resent quand tu dis ça, et c'est justifié, mais ne crois-tu pas qu'il est plus mauvais pour l'encapsulation d'avoir acces à tout, (c'est a dire exposter tout le contenu finale), plutot que de controler ce qui passe au travers d'accesseurs ?



                    Les variables finales c'est très bien, parfois contraignant je te l'accorde mais c'est clean.
                    Par contre que n'importe quelle classe puisse voir myClass.getTree(); alors qu'ils ne sont même pas sensé savoir que cette classe contient un Tree, ça me dérange.

                    Enfin en quoi une classe implémentée dans une autre risque t' elle de nuire à l'encapsulation, vu que
                    1) elle fait partie de la classe donc techniquement le contenu du wrapper lui est légitiment visible.
                    2) on contrôle l'implémentation au sein même de la classe, c'est donc le propriétaire de la classe qui modifie l'inner.

                    Citation : Kazou_

                    Techniquement si, mais plutôt difficile à mettre en place. Après il y a ce qui est le top, et ce qui est envisageable. Il y a un équilibre entre les deux. Utiliser trop de pattern est un anti-pattern comme on dit.


                    Même techniquement, les avancées dans les technologies font qu'on se retrouve constamment avec de nouveaux cas à appréhender, on ne peut donc prévoir toutes les implémentations possible (sans parler du code métier, il faudrait des siècles pour coder tous les cas de figure possibles).
                    Je ne sais pas si utiliser trop de pattern est un anti-pattern, par contre baser son code sur des pattern plutôt que les utiliser pour résoudre des problème en est clairement un, il faut donc en effet garder un équilibre vu que chaque situation est unique.

                    Citation : Kazou_

                    C'est en effet discutable. J'ai posté ça quand je devais les avoir à l'envers. Désolé si je fûs un peu agressif.



                    Y a pas mort d'homme, puis ça permet de débattre un peu, pas souvent l'occasion ici.
                    • Partager sur Facebook
                    • Partager sur Twitter

                    Héritage, classes abstraites et interfaces

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown