{"id":51,"date":"2017-09-09T15:32:41","date_gmt":"2017-09-09T15:32:41","guid":{"rendered":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/?p=51"},"modified":"2023-04-03T16:11:26","modified_gmt":"2023-04-03T16:11:26","slug":"heritage-et-polymorphisme","status":"publish","type":"post","link":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/2017\/09\/09\/heritage-et-polymorphisme\/","title":{"rendered":"H\u00e9ritage et Polymorphisme"},"content":{"rendered":"<section>\n<section class=\"toc-pause\">\n<h1>Surcharge de M\u00e9thodes\/Constructeur<\/h1>\n<\/section>\n<section>\n<h2>Surcharge de M\u00e9thodes<\/h2>\n<p>Il est possible de d\u00e9finir plusieurs m\u00e9thodes qui portent le m\u00eame nom. Dans ce cas on dit qu&#8217;il y a une surcharge de m\u00e9thode. Les m\u00e9thodes diff\u00e8re malgr\u00e9 tout<\/p>\n<ul>\n<li class=\"fragment\">Sur le nombre d&#8217;arguments<\/li>\n<li class=\"fragment\">Sur le type (et\/ou l&#8217;ordre) des arguments<\/li>\n<\/ul>\n<p class=\"fragment\">Si c&#8217;est le cas elles peuvent avoir des types de retour diff\u00e9rents mais \u00e7a n&#8217;a pas vraiment de sens de faire \u00e7a.<\/p>\n<\/section>\n<section>\n<h2>Surcharge de M\u00e9thodes<\/h2>\n<p>Lorsqu&#8217;il y a une surcharge de m\u00e9thode, Java tente de satisfaire l&#8217;appelle de la m\u00e9thode.<\/p>\n<pre><code class=\"java\">public class Main {\r\n    static public void hello(String name) {\r\n        System.out.println(\"Hello \"+name+\"!!!\");\r\n    }\r\n    static public void hello(String name, int age) {\r\n        System.out.println(\"Hello \"+name+\", you're \"+age+\" years old!!\");\r\n    }\r\n    static public void hello(int age, String name) {\r\n        System.out.println(\"Hello \"+name+\", you're \"+age+\" years old!!\");\r\n    }\r\n    public static void main(String[] args) {\r\n      hello(\"Alice\");  \/\/ retourne \"Hello Alice!!!\"\r\n      hello(\"Bob\", 38);\/\/ retourne \"Hello Bob, you're 38 years old!!\"\r\n      hello(38, \"Bob\");\/\/ retourne \"Hello Bob, you're 38 years old!!\"\r\n    }\r\n}<\/code><\/pre>\n<p><a href=\"https:\/\/repl.it\/DA6R\" target=\"_blank\" rel=\"noopener\">Run it!<\/a><\/p>\n<\/section>\n<section>\n<h2>Surcharge de M\u00e9thodes<\/h2>\n<p>Autre exemple: <a href=\"https:\/\/docs.oracle.com\/javase\/8\/javafx\/api\/javafx\/geometry\/Rectangle2D.html#i0\" target=\"_blank\" rel=\"noopener\">javafx.geometry.Rectangle2D<\/a><\/p>\n<p>Une m\u00e9thode peut appeler la methode qu&#8217;il surcharge pour \u00e9vit\u00e9 de r\u00e9\u00e9crire deux fois la m\u00eame chose. Dans la classe Rectangle2D, on peut supposer que <code>contains(Point2D p)<\/code>fait appelle \u00e0 <code>contains(double x, double y)<\/code>.<br \/>\n(<a href=\"http:\/\/hg.openjdk.java.net\/openjfx\/8\/master\/rt\/file\/777535dcf02c\/modules\/graphics\/src\/main\/java\/javafx\/geometry\/Rectangle2D.java#l122\" target=\"_blank\" rel=\"noopener\">v\u00e9rifier \u00e7a!!<\/a>)<\/p>\n<\/section>\n<section>\n<h2>Surcharge du Constructeur<\/h2>\n<p>Comme les autres m\u00e9thodes, le constructeur peut-\u00eatre surcharg\u00e9 (et c&#8217;est souvent le cas)<\/p>\n<p>Notamment, c&#8217;est tr\u00e8s pratique de proposer un constructeur par defaut (sans aucun param\u00e8tre) ou bien un constructeur de copy (prenant un objet de m\u00eame type en param\u00e8tre).<\/p>\n<\/section>\n<section>\n<h2>Surcharge du Constructeur<\/h2>\n<pre><code class=\"java\">public class Student {\r\n    private final int id;\r\n    private String name;\r\n\r\n    static private int lastStudentId;\r\n\r\n    public Student() {\r\n        this(null);\r\n    }\r\n    public Student(String name) {\r\n        this.id = lastStudentId + 1;\r\n        ++lastStudentId;\r\n\r\n        if(name == null) {\r\n            name = \"No Name\";\r\n        }\r\n        this.name = name;\r\n    }\r\n    public void setName(String n) {\r\n        name = n;\r\n    }\r\n    public String getName() {\r\n        return name;\r\n    }\r\n}<\/code><\/pre>\n<p>Dans un constructeur, on peut appeler un autre avec l&#8217;instruction <code>this(...)<\/code>. Dans ce case \u00e7a doit \u00eatre <b>la premi\u00e8re instruction du constructeur<\/b>.<\/p>\n<\/section>\n<section>\n<h2>Constructeur de Copie<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nclass Complex {\r\n\r\n    private double re, im;\r\n\r\n    public Complex(double re, double im) {\r\n        this.re = re;\r\n        this.im = im;\r\n    }\r\n    Complex(Complex c) {\r\n        re = c.re;\r\n        im = c.im;\r\n    }\r\n    public void add(Complex other) {\r\n        re += other.re;\r\n        im += other.im;\r\n    }\r\n    public void add(double re, double im) {\r\n        this.re += re;\r\n        this.im += im;\r\n    }\r\n    public String toString() {\r\n        return \"(\" + re + \" + \" + im + \"i)\";\r\n    }\r\n}\r\n\r\npublic class Main {\r\n\r\n    public static void main(String[] args) {\r\n        Complex c1 = new Complex(2, 2);\r\n        Complex c2 = c1;\r\n        Complex c3 = new Complex(c1);\r\n\r\n        c1.add(3,3);\r\n\r\n        System.out.println(c2);\r\n        System.out.println(c3);\r\n    }\r\n}\r\n                        <\/code><\/pre>\n<p><small>affiche : (<a href=\"https:\/\/repl.it\/DC7C\" target=\"_blank\" rel=\"noopener\">run it!<\/a>)<\/small><\/p>\n<pre class=\"fragment\"><code class=\"java\">(5.0 + 5.0i)\r\n(2.0 + 2.0i)<\/code><\/pre>\n<\/section>\n<section>\n<h2>Constructeur de Copie<\/h2>\n<p>D&#8217;ailleurs cette classe aurait int\u00e9r\u00eat \u00e0 \u00eatre immuable. Et dans ce cas un constructeur de copie n&#8217;est pas utile :<\/p>\n<pre><code class=\"java\" data-trim=\"\">\r\nfinal class Complex {\r\n\r\n    private final double re, im;\r\n\r\n    public Complex(double re, double im) {\r\n        this.re = re;\r\n        this.im = im;\r\n    }\r\n    public Complex add(Complex other) {\r\n        return add(other.re, other.im);\r\n    }\r\n    public Complex add(double re, double im) {\r\n        return new Complex(this.re + re, this.im + im);\r\n    }\r\n    public String toString() {\r\n        return \"(\" + re + \" + \" + im + \"i)\";\r\n    }\r\n}\r\n\r\npublic class Main {\r\n\r\n    public static void main(String[] args) {\r\n        Complex c1 = new Complex(2, 2);\r\n        Complex c2 = c1;\r\n\r\n        c1 = c1.add(3,3);\r\n\r\n        System.out.println(c2);\r\n    }\r\n}\r\n                        <\/code><\/pre>\n<p><small><a href=\"https:\/\/repl.it\/DC72\/1\" target=\"_blank\" rel=\"noopener\">run it!<\/a><\/small><\/section>\n<\/section>\n<section>\n<section class=\"toc-pause\">\n<h1>H\u00e9ritage<\/h1>\n<\/section>\n<section>\n<h2>Relation entre Objets (et Classes)<\/h2>\n<p>&nbsp;<\/p>\n<ul>\n<li>La composition\/agr\u00e9gation d&#8217;objets :<br \/>\n<small>l&#8217;objet de type A &#8220;A UN&#8221; objet de type B<\/small><\/li>\n<li>L&#8217;utilisation d&#8217;objets :<br \/>\n<small>l&#8217;objet de type A &#8220;UTILISE UN&#8221; objet de type B<\/small><\/li>\n<\/ul>\n<p>L&#8217;h\u00e9ritage introduit un nouveau type de relation :<br \/>\n<b>l&#8217;objet de type B &#8220;EST UN&#8221; objet de type A<\/b><\/p>\n<\/section>\n<section>\n<h2>H\u00e9ritage<\/h2>\n<p>Lorsqu&#8217;un objet de type B &#8220;EST UN&#8221; objet de type A, on dit que B h\u00e9rite des propri\u00e9t\u00e9s de A.<\/p>\n<ul>\n<li>A est la super-classe (ou classe m\u00e8re) de B<\/li>\n<li>B est une classe d\u00e9riv\u00e9e (ou sous-class ou classe fille) de A<\/li>\n<\/ul>\n<\/section>\n<section>\n<h2>H\u00e9ritage<\/h2>\n<p>Lorsqu&#8217;un objet de type B &#8220;EST UN&#8221; objet de type A, on dit que B h\u00e9rite des propri\u00e9t\u00e9s de A.<\/p>\n<p>Exercice : H\u00e9ritage, Agr\u00e9gation ou Utilisation ?<\/p>\n<ul>\n<li class=\"fragment\">Cercle et Ellipse ?<\/li>\n<li class=\"fragment\">Salle de bains et Baignoire ?<\/li>\n<li class=\"fragment\">Piano et Joueur de piano ?<\/li>\n<li class=\"fragment\">Entier et R\u00e9el ?<\/li>\n<li class=\"fragment\">Personne, Enseignant et Etudiant ?<\/li>\n<li class=\"fragment\">Appareil, Imprimante, Scanner et Copieur ?<\/li>\n<\/ul>\n<\/section>\n<section>\n<h2>Exemple<\/h2>\n<p>Probl\u00e8mes pour impl\u00e9menter cette sp\u00e9cification :<br \/>\nElle est trop g\u00e9n\u00e9rale : manger( ) diff\u00e8re suivant les animaux ;<br \/>\nIl manque les services sp\u00e9cifiques : voler( ), nager( ), &#8230;<\/p>\n<\/section>\n<section>\n<h2>Mauvaise Solutions<\/h2>\n<ul>\n<li>Faire autant de classe qu&#8217;il existe d&#8217;esp\u00e8ces animales :\n<ul>\n<li>=&gt; beaucoup de services similaires<\/li>\n<li>=&gt; cout \u00e9norme pour maintenanir le code<\/li>\n<\/ul>\n<\/li>\n<li>Modifier la classe Animal pour repr\u00e9senter tous les animaux :\n<ul>\n<li>Ajouter des m\u00e9thodes pour repr\u00e9senter toutes les choses que les animaux penvent faire<\/li>\n<li>Ajouter un attribut pour indiquer la cat\u00e9gorie (<code>isFish()<\/code>, <code>isBird()<\/code>)<\/li>\n<li>=&gt; complexit\u00e9 accrue, et co\u00fbt \u00e9norme pour \u00e9tendre le code<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/section>\n<section>\n<h2>Solution<\/h2>\n<p>Utiliser une hie\u0301rarchie de classe et faire de l\u2019he\u0301ritage<\/p>\n<\/section>\n<section>\n<h2>H\u00e9ritage<\/h2>\n<p>L&#8217;h\u00e9ritage est un concept essentiel en programmation orient\u00e9e objet.<\/p>\n<p class=\"fragment\">Il permet la r\u00e9utiliation des composants (les classes). Il permet la cr\u00e9ation d&#8217;une <b>classe d\u00e9riv\u00e9e<\/b> \u00e0 partir d&#8217;une <b>classe de base<\/b> et ainsi l&#8217;enrichir.<\/p>\n<p class=\"fragment\">Il permet aussi la cr\u00e9ation d&#8217;une hierarchie de <b>types<\/b> (la classe d\u00e9riv\u00e9e d\u00e9finie un sous-type de la classe de base).<\/p>\n<\/section>\n<section>\n<h2>H\u00e9ritage en Java<\/h2>\n<ol>\n<li>Une classe h\u00e9rite toujours d&#8217;une seule classe<\/li>\n<li class=\"fragment\">Par d\u00e9faut, une classe h\u00e9rite de la classe <code>Object<\/code><\/li>\n<li class=\"fragment\">Les cycles sont interdits<\/li>\n<\/ol>\n<\/section>\n<section>\n<h2>H\u00e9ritage<\/h2>\n<p>Supposons qu&#8217;on propose une classe <code>Point<\/code> qui repr\u00e9sente un point dans le plan :<\/p>\n<pre><code class=\"java\" data-trim=\"\">\r\nclass Point {\r\n    private double x, y;\r\n    public Point() {\r\n        x = Math.random()*100;\r\n        y = Math.random()*100;\r\n    }\r\n    public Point(double x, double y)\r\n    {\r\n        this.x = x; this.y = y;\r\n    }\r\n    public void add(int dx, double dy)\r\n    {\r\n        x += dx;\r\n        y += dy;\r\n    }\r\n    public double getX() { return x; }\r\n    public double getY() { return y; }\r\n}\r\n<\/code><\/pre>\n<\/section>\n<section>\n<h2>H\u00e9ritage<\/h2>\n<p>Et que l&#8217;on souhaite cr\u00e9er une classe <code>ColoredPoint<\/code> qui repr\u00e9sente un point color\u00e9 dans le plan.<\/p>\n<p class=\"fragment\">Alors on peut utiliser la classe <code>Point<\/code> et lui ajouter des propri\u00e9t\u00e9s. On l&#8217;indique au compilateur avec le mot cl\u00e9 <code>extends<\/code>.<\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nclass ColoredPoint extends Point {\r\n    private byte color;\r\n    public void setColor(byte c) { color = c; }\r\n    public byte getColor() { return color; }\r\n}\r\n<\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\n    ColoredPoint p = new ColoredPoint();\r\n    p.setColor((byte)50);\r\n    System.out.println(p.toString() + \" with color \" + p.getColor());\r\n<\/code><\/pre>\n<p><a href=\"https:\/\/repl.it\/DCoA\" target=\"_blank\" rel=\"noopener\">run it!<\/a><\/section>\n<section>\n<h2>H\u00e9ritage<\/h2>\n<p>Une classe d\u00e9riv\u00e9e <b>h\u00e9rite<\/b> des m\u00e9thodes et attributs publics de sa classe de base. Un objet de type <code>ColoredPoint<\/code> \u00e9tant aussi de type <code>Point<\/code> il peut donc utiliser les m\u00e9thodes <code>getX()<\/code>, <code>getY()<\/code> en plus de <code>getColor()<\/code>.<\/p>\n<p>Attention: une classe d\u00e9riv\u00e9 <b>n&#8217;a pas acc\u00e9s aux attributs et m\u00e9thodes priv\u00e9s<\/b>. Encore une fois, ce sont des d\u00e9tails d&#8217;impl\u00e9mentation qui ne doivent pas sortir de la classe.<\/p>\n<\/section>\n<section>\n<h2>H\u00e9ritage et Constructeur<\/h2>\n<p>Dans l&#8217;exemple pr\u00e9c\u00e9dent, lorsqu&#8217;un objet de type <code>ColoredPoint<\/code> est cr\u00e9e, on peut se demander si un constructeur de la class <code>Point<\/code> est appel\u00e9.<\/p>\n<p class=\"fragment\">La r\u00e9ponse est oui.<\/p>\n<p class=\"fragment\"><b>Juste avant que le constructeur de la classe <code>ColoredPoint<\/code> soit appel\u00e9, un constructeur de la classe de base est appel\u00e9.<\/b><\/p>\n<\/section>\n<section>\n<h2>H\u00e9ritage et Constructeur<\/h2>\n<p>Par d\u00e9faut, le constructeur par d\u00e9faut est appel\u00e9<\/p>\n<p>Mais on peut en choisir un autre avec l&#8217;instruction <code>super(...)<\/code>. Dans ce cas <b>\u00e7a doit \u00eatre la premi\u00e8re instruction du constructeur<\/b><\/p>\n<\/section>\n<section>\n<h2>H\u00e9ritage et Constructeur<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nclass ColoredPoint extends Point {\r\n    \/\/Choix 1\r\n    public ColoredPoint() {\r\n        color = (byte)(Math.random()*256);\r\n    }\r\n    \/\/Choix 2\r\n    public ColoredPoint() {\r\n        super();\r\n        color = (byte)(Math.random()*256);\r\n    }\r\n    \/\/Choix 3\r\n    public ColoredPoint() {\r\n        super(0, 0);\r\n        color = (byte)(Math.random()*256);\r\n    }\r\n}\r\n<\/code><\/pre>\n<p class=\"fragment\">Ici, les choix 1 et 2 sont \u00e9quivalent (c&#8217;est inutile d&#8217;\u00e9crire <code>super()<\/code>). Par contre dans le choix 3, le constructeur de Point est appel\u00e9 avec deux param\u00e8tres (les coordonn\u00e9es ne sont donc plus al\u00e9atoire mais initialis\u00e9 a 0).<\/p>\n<\/section>\n<section>\n<h2>H\u00e9ritage et Constructeur<\/h2>\n<p>Remarque: Les contructeurs ne sont pas h\u00e9rit\u00e9s au m\u00eame titre que les m\u00e9thodes publiques. Lors de la cr\u00e9ation d&#8217;un objet, un constructeur de la classe d\u00e9riv\u00e9e doit obligatoirement exister.<\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nclass ColoredPoint extends Point {\r\n    private byte color;\r\n    public ColoredPoint() {\r\n        color = (byte)(Math.random()*256);\r\n    }\r\n    public void setColor(byte c) { color = c; }\r\n    public byte getColor() { return color; }\r\n}\r\n<\/code><\/pre>\n<p class=\"fragment\">On ne peut pas faire <code>new ColoredPoint(10, 10)<\/code> m\u00eame si un contructeur de <code>Point<\/code> existe pour ces arguments.<\/p>\n<p class=\"fragment\"><small>bien s\u00fbr si aucun constructeur n&#8217;est d\u00e9fini, le compilateur en d\u00e9finit un par d\u00e9faut qui ne fait rien.<\/small><\/p>\n<\/section>\n<section>\n<h2>H\u00e9ritage et Constructeur<\/h2>\n<p>Pour \u00eatre coh\u00e9rent avec la classe <code>Point<\/code>, on peut faire :<\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nclass ColoredPoint extends Point {\r\n    private byte color;\r\n    public ColoredPoint() {\r\n        color = (byte)(Math.random()*256);\r\n    }\r\n    public ColoredPoint(double x, double y) {\r\n        super(x, y);\r\n        color = (byte)(Math.random()*256);\r\n    }\r\n    public ColoredPoint(double x, double y, byte c) {\r\n        super(x, y);\r\n        color = c;\r\n    }\r\n    public void setColor(byte c) { color = c; }\r\n    public byte getColor() { return color; }\r\n}\r\n<\/code><\/pre>\n<\/section>\n<section>\n<h2>Exemples<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nclass A {\r\n    public String a() { return \"A\"; }\r\n}\r\nclass B {\r\n    public String b() { return \"B\"; }\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nB o = new B();\r\no.a();\r\no.b();\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nB o = new B();\r\no.a(); \/\/retourne \"A\"\r\no.b(); \/\/retourne \"B\"\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>Exemples<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nclass A {\r\n    public String a() { return \"A\"; }\r\n}\r\nclass B {\r\n    private int i;\r\n    public B(int i) { this.i = i; } \/\/ Le constructeur par d\u00e9faut de A est appel\u00e9\r\n    public int b() { return i; }\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nB o = new B(10);\r\no.a()\r\no.b()\r\no = new B();\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nB o = new B(10);\r\no.a() \/\/retourne \"A\"\r\no.b() \/\/retourne 10\r\no = new B(); \/\/ Erreur de compilation\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>Exemples<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nclass A {\r\n    private int j;\r\n    public A(int j) { this.j = j; }\r\n    public String a() { return \"A\"; }\r\n}\r\nclass B {\r\n    private int i;\r\n    public B(int i) { this.i = i; }\r\n    public int b() { return i; }\r\n}\r\n                        <\/code><\/pre>\n<p class=\"fragment\">Erreur de compilation, aucun constructeur par d\u00e9faut n&#8217;existe pour <code>A<\/code><\/p>\n<\/section>\n<section>\n<h2>Exemples<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nclass A {\r\n    public A() { System.out.println(\"A created\"); }\r\n    public String a() { return \"A\"; }\r\n}\r\nclass B {\r\n    public String b() { return \"B\"; }\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nB o = new B();\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nB o = new B(); \/\/ Affiche \"A created\"\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>H\u00e9ritage<\/h2>\n<p>On peut v\u00e9rifier le type d&#8217;un objet avec le mot cl\u00e9 <code>instanceof<\/code>.<\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nPoint p = pointOrColoredPoint();\r\nif(p instanceof ColoredPoint){\r\n    ColoredPoint cp = (ColoredPoint)p;\r\n    System.out.println(cp.getColor());\r\n}\r\nif(p instanceof Point){\r\n    Point cp = (Point)p;\r\n    System.out.println(\"just a point\");\r\n} else {\r\n    System.out.println(\"just an object\");\r\n}\r\n                        <\/code><\/pre>\n<\/section>\n<\/section>\n<section>\n<section class=\"toc-pause\">\n<h1>Red\u00e9finition de M\u00e9thodes<\/h1>\n<\/section>\n<section>\n<h2>Red\u00e9finition de M\u00e9thodes<\/h2>\n<p>Que ce passe-t&#8217;il lorsqu&#8217;un m\u00e9thode d&#8217;une classe d\u00e9riv\u00e9e \u00e0 exactement la m\u00eame signature qu&#8217;une m\u00e9thode de la classe de base?<\/p>\n<p class=\"fragment\">C&#8217;est possible, et dans ce cas, c&#8217;est toujours la m\u00e9thode de la classe d\u00e9riv\u00e9e qui est appel\u00e9e.<\/p>\n<p class=\"fragment\"><small>remarque : si type de retour peut \u00eatre un sous-type du type de retour de la classe de base, on parle toujours de red\u00e9finition.<\/small><\/p>\n<\/section>\n<section>\n<h2>Red\u00e9finition de M\u00e9thodes<\/h2>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nclass A {\r\n    public String foo() { return \"I'm A\" }\r\n}\r\nclass B extends A {\r\n    @Override\r\n    public String foo() { return \"I'm B\" }\r\n}\r\n                        <\/code><\/pre>\n<p class=\"fragment\">Le mot cl\u00e9 <code>@Override<\/code> est appel\u00e9 une <b>annotation<\/b>. Ici elle indique au compilateur notre intention de red\u00e9finir une m\u00e9thode qui existe dans la super-classe.<br \/>\n<small class=\"fragment\">L&#8217;annotation <code>@Override<\/code> n&#8217;est pas obligatoire mais elle permet d&#8217;\u00eatre s\u00fbr qu&#8217;on n&#8217;a pas fait une faute de frappe lors de la red\u00e9finition.<\/small><\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nB b = new B();\r\nb.foo(); \/\/ return \"I'm B\"\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>Mot cl\u00e9 <code>super<\/code><\/h2>\n<p>Dans une m\u00e9thode d&#8217;une classe d\u00e9riv\u00e9, on peut appeler une m\u00e9thode de la super-classe avec le mot cl\u00e9 <code>super<\/code><\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nclass A {\r\n    public String foo() { return \"I'm A\" }\r\n}\r\nclass B extends A {\r\n    @Override\r\n    public String foo() { return super.foo()+\" and I'm B\" }\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nB b = new B();\r\nb.foo(); \/\/ return \"I'm A and I'm B\"\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>Surcharge de M\u00e9thodes<\/h2>\n<p>Si le type des arguments est diff\u00e9rent de ceux de la classe de base, alors c&#8217;est une <b>surcharge de m\u00e9thode<\/b> (comme c&#8217;est le cas au sein d&#8217;une classe).<\/p>\n<\/section>\n<section>\n<h2>Surcharge et Red\u00e9finition de M\u00e9thodes<\/h2>\n<p>Lorsqu&#8217;une m\u00e9thode est appel\u00e9 sur un objet, il y a une \u00e9tape de r\u00e9solution pour savoir qu&#8217;elle impl\u00e9mentation de la m\u00e9thode est utilis\u00e9 :<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>On consid\u00e8re la classe la plus d\u00e9riv\u00e9e dans la hi\u00e9rarchie d\u00e9finissant l&#8217;objet (celle qui a cr\u00e9er l&#8217;objet avec <code>new<\/code>).<\/li>\n<li>On regarde si la m\u00e9thode existe, avec les bon arguments.<\/li>\n<li>Si c&#8217;est le cas, on utilise cette m\u00e9thode, sinon on consid\u00e8re la classe parente (la super-classe) et on recommence au point pr\u00e9c\u00e9dent.<\/li>\n<li>Si il n&#8217;y a pas de classe parente, il y a une erreur.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<h2>Surcharge et Red\u00e9finition de M\u00e9thodes<\/h2>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nclass A {\r\n    String foo() { return \"I'm A\" }\r\n}\r\nclass B extends A {\r\n    String foo(int i) { return \"I'm B\" }\r\n}\r\nclass C extends A {\r\n    String foo() { return \"I'm C\" }\r\n}\r\nclass D extends C {\r\n    String foo() { return \"I'm D\" }\r\n}\r\nclass E extends C {\r\n    String foo(int i) { return \"I'm E\" }\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nB b = new B(); C c = new C(); D d = new D(); E e = new E();\r\nb.foo();\r\nb.foo(1);\r\nc.foo();\r\nc.foo(1);\r\nd.foo();\r\ne.foo();\r\ne.foo(1);\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nB b = new B(); C c = new C(); D d = new D(); E e = new E();\r\nb.foo();  \/\/ return \"I'm A\"\r\nb.foo(1);\r\nc.foo();\r\nc.foo(1);\r\nd.foo();\r\ne.foo();\r\ne.foo(1);\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nB b = new B(); C c = new C(); D d = new D(); E e = new E();\r\nb.foo();  \/\/ return \"I'm A\"\r\nb.foo(1); \/\/ return \"I'm B\"\r\nc.foo();\r\nc.foo(1);\r\nd.foo();\r\ne.foo();\r\ne.foo(1);\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nB b = new B(); C c = new C(); D d = new D(); E e = new E();\r\nb.foo();  \/\/ return \"I'm A\"\r\nb.foo(1); \/\/ return \"I'm B\"\r\nc.foo();  \/\/ return \"I'm C\"\r\nc.foo(1);\r\nd.foo();\r\ne.foo();\r\ne.foo(1);\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nB b = new B(); C c = new C(); D d = new D(); E e = new E();\r\nb.foo();  \/\/ return \"I'm A\"\r\nb.foo(1); \/\/ return \"I'm B\"\r\nc.foo();  \/\/ return \"I'm C\"\r\nc.foo(1); \/\/ erreur\r\nd.foo();\r\ne.foo();\r\ne.foo(1);\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nB b = new B(); C c = new C(); D d = new D(); E e = new E();\r\nb.foo();  \/\/ return \"I'm A\"\r\nb.foo(1); \/\/ return \"I'm B\"\r\nc.foo();  \/\/ return \"I'm C\"\r\nc.foo(1); \/\/ erreur\r\nd.foo();  \/\/ return \"I'm D\"\r\ne.foo();\r\ne.foo(1);\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nB b = new B(); C c = new C(); D d = new D(); E e = new E();\r\nb.foo();  \/\/ return \"I'm A\"\r\nb.foo(1); \/\/ return \"I'm B\"\r\nc.foo();  \/\/ return \"I'm C\"\r\nc.foo(1); \/\/ erreur\r\nd.foo();  \/\/ return \"I'm D\"\r\ne.foo();  \/\/ return \"I'm C\"\r\ne.foo(1);\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nB b = new B(); C c = new C(); D d = new D(); E e = new E();\r\nb.foo();  \/\/ return \"I'm A\"\r\nb.foo(1); \/\/ return \"I'm B\"\r\nc.foo();  \/\/ return \"I'm C\"\r\nc.foo(1); \/\/ erreur\r\nd.foo();  \/\/ return \"I'm D\"\r\ne.foo();  \/\/ return \"I'm C\"\r\ne.foo(1); \/\/ return \"I'm E\"\r\n                        <\/code><\/pre>\n<\/section>\n<\/section>\n<section>\n<section class=\"toc-pause\">\n<h1>Polymorphisme<\/h1>\n<\/section>\n<section>\n<h2>Polymorphisme<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nclass A {\r\n    String foo() { return \"I'm A\" }\r\n}\r\n                        <\/code><\/pre>\n<pre><code class=\"java\" data-trim=\"\">\r\nA a = generateSomething();\r\nSystem.out.println(a.foo());\r\n                        <\/code><\/pre>\n<p>Consid\u00e9rons cet exemple, qu&#8217;affiche notre programme?<\/p>\n<p class=\"fragment\">Il semblerait que ce soit &#8220;I&#8217;m A&#8221; <span class=\"fragment\">, mais<\/span><\/p>\n<p class=\"fragment\"><b>on ne peut pas en \u00eatre s\u00fbr!!<\/b><\/p>\n<\/section>\n<section>\n<h2>Polymorphisme<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nclass A {\r\n    String foo() { return \"I'm A\" }\r\n}\r\nclass B extends A {\r\n    String foo() { return \"I'm B\" }\r\n}\r\nA generateSomethin() { return new B(); }\r\n                        <\/code><\/pre>\n<pre><code class=\"java\" data-trim=\"\">\r\nA a = generateSomethin();\r\nSystem.out.println(a.foo());\r\n                        <\/code><\/pre>\n<p class=\"fragment\"><b>Dans ce cas, notre programme affiche &#8220;I&#8217;m B&#8221;<\/b>. Car l&#8217;objet <code>a<\/code> a \u00e9t\u00e9 d\u00e9fini par la classe <code>B<\/code> m\u00eame s&#8217;il est stock\u00e9 dans une variable de type <code>A<\/code>. <small>Donc lors de l&#8217;\u00e9xecution de la m\u00e9thode <code>foo<\/code>, la classe la plus d\u00e9riv\u00e9e (ici B) qui poss\u00e8de la m\u00e9thode et donc utilis\u00e9e.<\/small><\/p>\n<p class=\"fragment\">C&#8217;est ce qu&#8217;on appelle <b>le polymorphisme.<\/b><\/p>\n<\/section>\n<section>\n<h2>Polymorphisme<\/h2>\n<p><b>Le polymorphisme est le concept consistant \u00e0 fournir une interface unique \u00e0 des entit\u00e9s pouvant avoir diff\u00e9rents types (wikipedia).<\/b><\/p>\n<p class=\"fragment\">On pourra remarquer que la surcharge de m\u00e9thode est aussi consid\u00e9r\u00e9 comme du polymorphisme.<\/p>\n<p class=\"fragment\">Lorsqu&#8217;il provient d&#8217;une red\u00e9finition de m\u00e9thode, on l&#8217;appelle polymorphisme par sous-typage.<\/p>\n<\/section>\n<section>\n<h2>Polymorphisme<\/h2>\n<p>En clair, \u00e7a signifie que lorsqu&#8217;on appelle une m\u00e9thode sur un objet, l&#8217;impl\u00e9mentation choisie d\u00e9pend du type r\u00e9el de l&#8217;objet (la classe qui a cr\u00e9e l&#8217;objet) et ne d\u00e9pends pas du type de la variable qui stocke l&#8217;objet.<\/p>\n<p class=\"fragment\">Cela permet <b>d&#8217;appeler la m\u00eame m\u00e9thode sur des objets sans se soucier de leur type!!<\/b><\/p>\n<\/section>\n<section>\n<h2>Polymorphisme<\/h2>\n<p>Cela permet <b>d&#8217;appeler la m\u00eame m\u00e9thode sur des objets sans se soucier de leur type!!<\/b><\/p>\n<pre><code class=\"java\" data-trim=\"\">\r\nAnimal animals = NoahsArk.listAnimals();\r\nfor(Animal a : animals) {\r\n    a.speak();\r\n}\r\n                        <\/code><\/pre>\n<p>Ici, on fait parler tous les animaux quelque soit leur type.<\/p>\n<\/section>\n<section>\n<h2>Polymorphisme<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nclass Animal {\r\n    public void speak() { System.out.println(\"who am I?\"); }\r\n}\r\nclass Dog extends Animal{\r\n    public void speak() { System.out.println(\"I'm a dog\"); }\r\n}\r\nclass Cat extends Animal{\r\n    public void speak() { System.out.println(\"I'm a cat\"); }\r\n}\r\nclass Squirrel extends Animal{\r\n    public void speak() { System.out.println(\"I'm a squirrel\"); }\r\n}\r\nclass Dolphin extends Animal{\r\n    public void speak() { System.out.println(\"I'm a dolphin\"); }\r\n}\r\nclass Duck extends Animal{\r\n    public void speak() { System.out.println(\"I'm a duck\"); }\r\n}\r\nclass Parrot extends Animal{\r\n    public void speak() { System.out.println(\"I'm a parrot\"); }\r\n}\r\n\r\nclass NoahsArk {\r\n    static Animal[] listAnimals() {\r\n        Animal[] animals = new Animal[6];\r\n        animals[0] = new Dog();\r\n        animals[1] = new Squirrel();\r\n        animals[2] = new Cat();\r\n        animals[3] = new Dolphin();\r\n        animals[4] = new Duck();\r\n        animals[5] = new Parrot();\r\n        return animals;\r\n    }\r\n}\r\nclass Main {\r\n  public static void main(String[] args) {\r\n    Animal[] animals = NoahsArk.listAnimals();\r\n    for(Animal a : animals) {\r\n        a.speak();\r\n    }\r\n  }\r\n}\r\n                        <\/code><\/pre>\n<p><a href=\"https:\/\/repl.it\/DF8Q\" target=\"_blank\" rel=\"noopener\">run it!<\/a><\/p>\n<\/section>\n<\/section>\n<section>\n<section class=\"toc-pause\">\n<h1>Package et Visibilit\u00e9<\/h1>\n<\/section>\n<section>\n<h2>Package (Paquetage en fran\u00e7ais)<\/h2>\n<p>Un paquetage est une biblioth\u00e8que d&#8217;objets, un ensemble de classes <b>(dans un m\u00eame r\u00e9pertoire)<\/b>.<\/p>\n<p>Les paquetages permettent :<\/p>\n<ul>\n<li class=\"fragment\"><b>de structurer le projet :<\/b> les classes sont tri\u00e9es dans des r\u00e9pertoires.<\/li>\n<li class=\"fragment\"><b>d&#8217;\u00e9vit\u00e9 les conflits de nom :<\/b> des classes de m\u00eame nom peuvent exister dans des packages diff\u00e9rents.<\/li>\n<li class=\"fragment\"><b>d&#8217;affiner la visibilit\u00e9.<\/b><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<h2>Package<\/h2>\n<p>Pour cr\u00e9er un paquetage, il suffit de cr\u00e9er un r\u00e9pertoire dont le nom est en minuscule (c&#8217;est le nom du paquetage)<\/p>\n<p class=\"fragment\">Pour faire partie du paquetage, une classe doit se trouver dans ce r\u00e9pertoire et la premi\u00e8re ligne du fichier de la class contient le mot cl\u00e9 <code>package<\/code> suivit du nom du paquetage.<\/p>\n<p class=\"fragment\">Exemple, dans un fichier <code>\/....\/pim\/Poum.java<\/code>:<\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\npackage pim;\r\n\r\npublic class Poum {\r\n   ...\r\n}\r\n\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>Package<\/h2>\n<p>Un paquetage peut contenir d&#8217;autre paquetage. On peut ainsi cr\u00e9e une hi\u00e9rarchie compl\u00e8te.<\/p>\n<p class=\"fragment\">Exemple, dans un fichier <code>\/....\/pim\/pam\/Poum.java<\/code>:<\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\npackage pim.pam;\r\n\r\npublic class Poum {\r\n   ...\r\n}\r\n                        <\/code><\/pre>\n<p class=\"fragment\"><small>Il est courant dans les biblioth\u00e8ques disponibles sur internet, de trouver des noms de packages contenant une url invers\u00e9e. Cela permet d&#8217;\u00e9viter les collisions entre biblioth\u00e8ques.<\/small><\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\npackage org.json.simple; \/\/ nom du package de la libraire json-simple qui permet de parser du json\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\npackage org.json.simple.parser; \/\/ Cette bibliot\u00e8que contient un sous-package parser, ajout\u00e9 \u00e0 la suite de l'url invers\u00e9e.\r\n                        <\/code><\/pre>\n<p>Autre exemple de paquetage <a href=\"https:\/\/docs.oracle.com\/javase\/8\/javafx\/api\/javafx\/scene\/control\/package-summary.html\" target=\"_blank\" rel=\"noopener\">javafx.scene.control<\/a><\/p>\n<\/section>\n<section>\n<h2>Visibilit\u00e9<\/h2>\n<p>On a vu les mots cl\u00e9 <code>public<\/code> et <code>private<\/code> pour indiquer qu&#8217;une m\u00e9thode ou un attribut est visible en dehors de la classe ou non.<\/p>\n<p class=\"fragment\">On a vu aussi qu&#8217;un attribut <code>private<\/code> est visible dans la classe <b>mais pas dans les classes d\u00e9riv\u00e9es<\/b>.<\/p>\n<p><img decoding=\"async\" class=\"stretch fragment\" src=\"https:\/\/pagesperso.lip6.fr\/Maria.Gradinariu\/sites\/Maria.Gradinariu\/IMG\/html\/c2-figures\/visibilite-private.png\" \/><\/section>\n<section>\n<h2>Visibilit\u00e9 &#8211; protected<\/h2>\n<p><b>Le mot cl\u00e9 <code>protected<\/code> \u00e9tend la visibilit\u00e9 aux classes d\u00e9riv\u00e9es.<\/b><\/p>\n<p><img decoding=\"async\" class=\"stretch fragment\" src=\"https:\/\/pagesperso.lip6.fr\/Maria.Gradinariu\/sites\/Maria.Gradinariu\/IMG\/html\/c2-figures\/visibilite-protected.png\" \/><\/section>\n<section>\n<h2>Visibilit\u00e9 &#8211; par d\u00e9faut<\/h2>\n<p><b>Par d\u00e9faut (aucun mot cl\u00e9), un attribut ou une m\u00e9thode n&#8217;est visible que dans le package.<\/b><\/p>\n<p><img decoding=\"async\" class=\"stretch fragment\" src=\"https:\/\/pagesperso.lip6.fr\/Maria.Gradinariu\/sites\/Maria.Gradinariu\/IMG\/html\/c2-figures\/visibilite-default.png\" \/><\/section>\n<section>\n<h2>Visibilit\u00e9 &#8211; par d\u00e9faut<\/h2>\n<p>Attention : la visibilit\u00e9 protected \u00e9tant la visibilit\u00e9 par d\u00e9faut. Donc un \u00e9l\u00e9ment protected est accessbile par toutes les classes du paquetage et \u00e0 toutes les sous-classes (m\u00eame dans d&#8217;autre package)<\/p>\n<p><img decoding=\"async\" class=\"stretch\" src=\"https:\/\/pagesperso.lip6.fr\/Maria.Gradinariu\/sites\/Maria.Gradinariu\/IMG\/html\/c2-figures\/visibilite-default.png\" \/><\/section>\n<section>\n<h2>Visibilit\u00e9<\/h2>\n<p>&nbsp;<\/p>\n<ul>\n<li>El\u00e9ment private : visible uniquement au sein de la classe.<\/li>\n<li class=\"fragment\">El\u00e9ment par d\u00e9faut : visible en plus au sein du m\u00eame paquetage.<\/li>\n<li class=\"fragment\">El\u00e9ment protected : visible en plus au sein des classes d\u00e9riv\u00e9es.<\/li>\n<li class=\"fragment\">El\u00e9ment public : visible partout.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<h2>Visibilit\u00e9<\/h2>\n<p>Les classes dans un m\u00eame r\u00e9pertoire sont consid\u00e9r\u00e9es comme appartenant au m\u00eame paquetage, m\u00eame si celui-ci n&#8217;est pas d\u00e9clar\u00e9 au d\u00e9but du fichier avec le mot cl\u00e9 <code>package<\/code> (c&#8217;est un paquetage sans nom).<\/p>\n<\/section>\n<section>\n<h2>Utilisation des Paquetages<\/h2>\n<p>Comment utiliser une classe qui se trouve dans un paquetage?<\/p>\n<pre><code class=\"java\" data-trim=\"\">\r\npackage pim.pam;\r\n\r\npublic class Poum {\r\n   ...\r\n}\r\n                        <\/code><\/pre>\n<p class=\"fragment\">En indiquand devant le nom de la classe, le nom du paquetage<\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\npublic class Main {\r\n    public static void main(String[] args) {\r\n        pim.pam.Poum p = new pim.pam.Poum();\r\n        p.poum();\r\n    }\r\n}\r\n\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>Utilisation des Paquetages<\/h2>\n<p>Ou bien, en important la classe du paquetage et ensuite utiliser la classe normalement (mot cl\u00e9 <code>import<\/code>) :<\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nimport pim.pam.Poum;\r\n\r\npublic class Main {\r\n    public static void main(String[] args) {\r\n        Poum p = new Poum();\r\n        p.poum();\r\n    }\r\n}\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>Import de Classes<\/h2>\n<p>Pour utiliser les fonctionnalit\u00e9s d&#8217;un package, il est souvent n\u00e9c\u00e9ssaire d&#8217;importer de nombreuses classes.<\/p>\n<p>C&#8217;est, par exemple, le cas avec les entr\u00e9es\/sorties du package java.io<\/p>\n<pre><code class=\"java\" data-trim=\"\">\r\nimport java.io.InputStream;\r\nimport java.io.DataInputStream;\r\nimport java.io.BufferedInputStream;\r\n\r\npublic class Test {\r\n    public static void main (String[] args) {\r\n        InputStream is = new InputStream();\r\n        DataInputStream dis = new DataInputStream(is);\r\n        BufferedInputStream bdis = new BufferedInputStream(dis);\r\n        ...\r\n    }\r\n}\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>Import de Classes<\/h2>\n<p>Dans ce cas, on peut importer toutes les classes d&#8217;un paquetage avec l&#8217;ast\u00e9risque.<\/p>\n<pre><code class=\"java\" data-trim=\"\">\r\n                        import nomPackage.*\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nimport java.io.*;\r\n\r\npublic class Test {\r\n    public static void main (String[] args) {\r\n        InputStream is = new InputStream();\r\n        DataInputStream dis = new DataInputStream(is);\r\n        BufferedInputStream bdis = new BufferedInputStream(dis);\r\n        ...\r\n    }\r\n}\r\n                        <\/code><\/pre>\n<p class=\"fragment\">Attention : ceci n&#8217;importe pas les classes des sous-paquetages (ce n&#8217;est pas r\u00e9cursif).<\/p>\n<\/section>\n<\/section>\n<section>\n<section class=\"toc-pause\">\n<h1>La Classe <code>Object<\/code><\/h1>\n<\/section>\n<section>\n<h2>la Classe <code>Object<\/code><\/h2>\n<p>On a vu que par d\u00e9faut une classe h\u00e9rite de la classe <code>Object<\/code><\/p>\n<p class=\"fragment\">Sinon, elle h\u00e9rite d&#8217;une autre classe, qui elle h\u00e9rite de la classe <code>Object<\/code><\/p>\n<p class=\"fragment\">Donc dans tous les cas, elle h\u00e9rite de la classe <code>Object<\/code>, directement ou indirectement<\/p>\n<\/section>\n<section>\n<h2>l&#8217;Objet <code>Object<\/code><\/h2>\n<p>On a vu que toutes les classes h\u00e9ritent de la classe <code>Object<\/code>.<\/p>\n<p class=\"fragment\">Donc, toutes les classes h\u00e9ritent des m\u00e9thodes publiques de cette classe. <a href=\"https:\/\/docs.oracle.com\/javase\/7\/docs\/api\/java\/lang\/Object.html\" target=\"_blank\" rel=\"noopener\">doc<\/a><\/p>\n<p class=\"fragment\">Donc sur tous les objets, m\u00eame sans connaitre leur type, on peut appeler ces m\u00e9thodes.<\/p>\n<p class=\"fragment\">Parmis ces m\u00e9thodes, 3 sont particuli\u00e8rement importantes.<\/p>\n<\/section>\n<section>\n<h2>M\u00e9thode <code>toString()<\/code><\/h2>\n<p>Elle permet de repr\u00e9senter\/d\u00e9crire l&#8217;objet sous forme de chaine de charact\u00e8res.<\/p>\n<p class=\"fragment\">Par d\u00e9faut elle affiche l&#8217;adresse m\u00e9moire de l&#8217;objet, <b>il est important de la red\u00e9finir au sein de chaque classe.<\/b><\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\npublic class Person {\r\n    private int birthYear;\r\n    private String name;\r\n    public Person(String name, int birthYear) {\r\n        this.name = name; this.birthYear = birthYear;\r\n    }\r\n    @Override\r\n    public String toString() {\r\n        return \"I'm \"+name+\", I'm \"+getAge()+\" years old.\";\r\n    }\r\n    public int getAge() { return 2017 - birthYear; }\r\n}\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>M\u00e9thode <code>toString()<\/code><\/h2>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nObject alice = new Person(\"Alice\", 1977);\r\nSystem.out.println(alice.toString());\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nSystem.out.println(alice);\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nSystem.out.println(alice); \/\/ Java converti automatiquement un objet en String en utilisant la m\u00e9thode toString()\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nSystem.out.println(\"I've created an object: \"+alice);\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nSystem.out.println(\"I've created an object: \"+alice); \/\/ idem\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nSystem.out.println(alice.getAge());\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nSystem.out.println(alice.getAge()); \/\/ Erreur de compilation, la classe Object n'a pas de m\u00e9thode getAge()\r\n                        <\/code><\/pre>\n<p class=\"fragment\"><small>A la compilation, Java v\u00e9rifie que la m\u00e9thode appel\u00e9e existe dans la classe contenant l&#8217;objet.<\/small><\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nSystem.out.println(((Person)alice).getAge()); \/\/ ok\r\n                        <\/code><\/pre>\n<p class=\"fragment\"><small>On peut convertir un objet dans un type d\u00e9riv\u00e9. La compilation se passe bien. <b>Mais pendant l&#8217;ex\u00e9cution, il peut se produire une erreur si l&#8217;objet n&#8217;est pas du type donn\u00e9.<\/b><\/small><\/p>\n<\/section>\n<section>\n<h2>M\u00e9thode <code>equals()<\/code><\/h2>\n<p>Elle permet de comparer deux objets. Elle retourne <code>true<\/code> si les deux objets sont identiques.<\/p>\n<p class=\"fragment\">Par d\u00e9faut, cette m\u00e9thode retourne <code>true<\/code> si et seulement si les objets correspondent exactement au m\u00eame objet en m\u00e9moire (<code>ob1 == ob2<\/code>).<\/p>\n<p class=\"fragment\">Lorsqu&#8217;on chosit de red\u00e9finir cette m\u00e9thode alors, intuitivement, elle doit \u00eatre :<\/p>\n<ul>\n<li class=\"fragment\">R\u00e9flexive : <span class=\"fragment\"><code>x.equals(x)<\/code> retourne <code>true<\/code>.<\/span><\/li>\n<li class=\"fragment\">Sym\u00e9trique : <span class=\"fragment\">si <code>x.equals(y)<\/code> alors <code>y.equals(x)<\/code>.<\/span><\/li>\n<li class=\"fragment\">Transitive : <span class=\"fragment\">si <code>x.equals(y)<\/code> et <code>y.equals(z)<\/code> alors <code>x.equals(z)<\/code>.<\/span><\/li>\n<li class=\"fragment\">Coh\u00e9rente : <span class=\"fragment\">des appelles successifs retournent la m\u00eame valeur.<\/span><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<h2>M\u00e9thode <code>equals()<\/code><\/h2>\n<p>Il est parfois int\u00e9ressant de red\u00e9finir cette m\u00e9thode.<\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\npublic class Person {\r\n    private int birthYear;\r\n    private String name;\r\n    public Person(String name, int birthYear) {\r\n        this.name = name; this.birthYear = birthYear;\r\n    }\r\n    @Override\r\n    public boolean equals(Object other) {\r\n        if(other == null ||\u00a0this.getClass() != other.getClass())\u00a0\r\n            return false;\r\n\r\n        Person p = (Person)other;\r\n        return name == p.name &amp;&amp; birthYear == p.birthYear;\r\n    }\r\n}\r\n                        <\/code><\/pre>\n<p class=\"fragment\"><small>Ici on consid\u00e8re que deux objets de type Person sont egaux si et seulement si ils ont le m\u00eame nom et la m\u00eame ann\u00e9e de naissance.<\/small><\/p>\n<\/section>\n<section>\n<h2>M\u00e9thode <code>equals()<\/code><\/h2>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nObject alice = new Person(\"Alice\", 1977);\r\nObject aliceBis = new Person(\"Alice\", 1977);\r\nObject bob = new Person(\"Bob\", 1978);\r\nObject bobBis = bob;\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nalice == aliceBis\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nalice == aliceBis \/\/ false\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nalice.equals(aliceBis);\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nalice.equals(aliceBis); \/\/ true\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nalice.equals(bob);\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nalice.equals(bob); \/\/ false\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nbob == aliceBis\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nbob == bobBis \/\/ true\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nbob.equals(bobBis);\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nbob.equals(bobBis); \/\/ true\r\n                        <\/code><\/pre>\n<p>Exemple de la classe Arrays :<\/p>\n<p>&#8220;Returns true if the two specified arrays of Objects are equal to one another. The two arrays are considered equal if both arrays contain the same number of elements, and all corresponding pairs of elements in the two arrays are equal.&#8221;<\/p>\n<\/section>\n<section>\n<h2>M\u00e9thode <code>hashCode()<\/code><\/h2>\n<p>Elle permet de repr\u00e9senter l&#8217;objet sous la forme d&#8217;un entier.<\/p>\n<p class=\"fragment\">C&#8217;est utile pour certaines biblioth\u00e8ques, qui veulent r\u00e9partir des objets quelconques dans des tableau par exemple.<\/p>\n<p class=\"fragment\">Il est important de red\u00e9finir cette m\u00e9thode lorsque l&#8217;on a red\u00e9finit la m\u00e9thode <code>equals()<\/code><\/p>\n<p class=\"fragment\">Surtout pour la raison suivante : La m\u00e9thode <code>hashCode()<\/code> doit retourner des valeurs identiques pour deux objets identiques (au sens de la m\u00e9thode <code>equals()<\/code>)<\/p>\n<\/section>\n<section>\n<h2>M\u00e9thode <code>hashCode()<\/code><\/h2>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\npublic class Person {\r\n    private int birthYear;\r\n    private String name;\r\n    public Person(String name, int birthYear) {\r\n        this.name = name; this.birthYear = birthYear;\r\n    }\r\n    @Override\r\n    public boolean equals(Object other) {\r\n        if(other == null ||\u00a0this.getClass() != other.getClass())\u00a0\r\n            return false;\r\n\r\n        Person p = (Person)other;\r\n        return name == p.name &amp;&amp; birthYear == p.birthYear;\r\n    }\r\n    @Override\r\n    public int hashcode() {\r\n        return 1;\r\n    }\r\n}\r\n                        <\/code><\/pre>\n<p class=\"fragment\">Erreur de compilation : <code>error: method does not override or implement a method from a supertype<\/code>. Sans l&#8217;annotation @Override, la compilation aurait fonctionn\u00e9 !!<\/p>\n<\/section>\n<section>\n<h2>M\u00e9thode <code>hashCode()<\/code><\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\npublic class Person {\r\n    private int birthYear;\r\n    private String name;\r\n    public Person(String name, int birthYear) {\r\n        this.name = name; this.birthYear = birthYear;\r\n    }\r\n    @Override\r\n    public boolean equals(Object other) {\r\n        if(other == null || this.getClass() != other.getClass())\u00a0\r\n            return false;\r\n\r\n        Person p = (Person)other;\r\n        return name == p.name &amp;&amp; birthYear == p.birthYear;\r\n    }\r\n    @Override\r\n    public int hashCode() {\r\n        return 1;\r\n    }\r\n}<\/code><\/pre>\n<p class=\"fragment\">Cette red\u00e9finition de <code>hashCode()<\/code> est correcte, mais le but est d&#8217;essayer dans la mesure du possible de renvoyer des valeurs diff\u00e9rentes pour des objets diff\u00e9rents.<\/p>\n<\/section>\n<section>\n<h2>M\u00e9thode <code>hashCode()<\/code><\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\npublic class Person {\r\n    private int birthYear;\r\n    private String name;\r\n    public Person(String name, int birthYear) {\r\n        this.name = name; this.birthYear = birthYear;\r\n    }\r\n    @Override\r\n    public boolean equals(Object other) {\r\n        if(other == null ||\u00a0this.getClass() != other.getClass())\u00a0\r\n            return false;\r\n\r\n        Person p = (Person)other;\r\n        return name == p.name &amp;&amp; birthYear == p.birthYear;\r\n    }\r\n    @Override\r\n    public int hashCode() {\r\n        return 7 * name.hashCode() + 37 * birthYear;\r\n    }\r\n}\r\n                        <\/code><\/pre>\n<p class=\"fragment\">Comme \u00e7a c&#8217;est mieux!!<\/p>\n<\/section>\n<\/section>\n<section>\n<h2>Mot Cl\u00e9 <code>final<\/code><\/h2>\n<p>Le mot cl\u00e9 <code>final<\/code> peut \u00eatre utilis\u00e9 pour une classe ou une m\u00e9thode.<\/p>\n<p>Dans ce cas, la classe ne peut pas \u00eatre d\u00e9riv\u00e9e, resp. la m\u00e9thode ne peux pas \u00eatre red\u00e9finie.<\/p>\n<\/section>\n<section>\n<h2>Objets Immuables<\/h2>\n<p>Une classe A qui ne contient que des attributs <code>final<\/code> et qui ne poss\u00e8de pas de mutateurs n&#8217;est pas forc\u00e9ment immuable.<\/p>\n<p>En effet, lorsqu&#8217;on manipule un objet de type A, c&#8217;est peut-\u00eatre en faite un objet de sous-type B, qui lui poss\u00e8de des attributs non <code>final<\/code><\/p>\n<p>&gt; Pour construire des objets immuables, il faut donc une classe sans modificateurs <b>et ne pouvant pas \u00eatre d\u00e9riv\u00e9e (donc une classe finale)<\/b><\/p>\n<\/section>\n","protected":false},"excerpt":{"rendered":"<p>Surcharge de M\u00e9thodes\/Constructeur Surcharge de M\u00e9thodes Il est possible de d\u00e9finir plusieurs m\u00e9thodes qui portent le m\u00eame nom. Dans ce cas on dit qu&#8217;il y a une surcharge de m\u00e9thode. Les m\u00e9thodes diff\u00e8re malgr\u00e9 tout Sur le nombre d&#8217;arguments Sur le type (et\/ou l&#8217;ordre) des arguments Si c&#8217;est le cas elles peuvent avoir des types [&hellip;]<\/p>\n","protected":false},"author":55,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-51","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/posts\/51","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/users\/55"}],"replies":[{"embeddable":true,"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/comments?post=51"}],"version-history":[{"count":1,"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/posts\/51\/revisions"}],"predecessor-version":[{"id":52,"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/posts\/51\/revisions\/52"}],"wp:attachment":[{"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/media?parent=51"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/categories?post=51"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/tags?post=51"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}