C à Java - IRIFpadovani/Cours_Java_M2BI/Slides... · 2018. 10. 8. · 2. Objets, Classes et...

97

Transcript of C à Java - IRIFpadovani/Cours_Java_M2BI/Slides... · 2018. 10. 8. · 2. Objets, Classes et...

  • Programmation en Java

    V.Padovani, PPS, Paris-Diderot

    Programmation en Java 1

  • PARTIE I - Classes et Objets

    • Eléments ommuns à C et Java

    • Classes, objets et référenes

    • Initialisation des objets : les onstruteurs

    • Modi�ation des objets : les méthodes.

    Programmation en Java 2

  • 1. De C à Java

    1.1. Eléments de base du langage

    éléments ommuns à C et Java :

    • notions de variable, de typage, d'a�etation,

    • types numériques int, float, double, et.

    • opérateurs arithmétiques + *, -, /, ++, �-, et.

    • opérateurs de omparaison ,

    • onditions, onneteurs ||, &&, !,• strutures if/else, for, while, do/while, swith,

    • ?/:, break, ontinue

    les variables se délarent à la volée (6= C ANSI).

    Programmation en Java 3

  • • un type boolean de onstantes true, false.

    int x, y = 10, z = 20;

    boolean b = (x == 3) && (y + 10 < z);

    • Les onditions doivent être de type booléen :

    if (x != 0) { ... } // et non if (x), omme en C.

    • Un for peut avoir un ompteur loal :

    for (int i = 0; i < n; i++) {

    // i delare et visible seulement

    // dans le orps de la boule,

    }

    Programmation en Java 4

  • 1.2. Syntaxe des tableaux

    • délarés et rées :

    � à l'aide de l'opérateur new :

    int[℄ t = new int[100℄;

    � ou par desription expliite :

    int[℄ u = {2,3,0,1};

    même syntaxe d'a

    ès qu'en C : t[i℄ = 42; et.

    • int[℄ est le type des tableaux d'entiers.

    • Les tableaux sont gratuitement initialisés à 0.

    Programmation en Java 5

  • • la taille des tableaux est libre (plus de mallo/free) :

    double[℄ t = new double[n + 42℄;

    • t.length vaut le nombre d'éléments de t.

    • les a

    ès sont véri�és à l'exéution.

    les a

    ès invalides interrompent l'exéution.

    har[℄ t = new har[100℄;

    /** t[-1℄ = 'a'; // erreur d'exeution

    * t[100℄ = 'a'; // erreur d'exeution

    */

    Programmation en Java 6

  • 1.3. A�hage

    • équivalents de printf :

    � System.out.print

    � System.out.println (retour à la ligne)

    • plus besoin de spéi�ateurs de format :

    for (int i = 0; i < 10; i++) {

    System.out.print("le arre de");

    System.out.print(i);

    System.out.print(" est ");

    System.out.println(i * i);

    }System.out.println('a');

    System.out.println(3.14); // et.

    Programmation en Java 7

  • • System.out.print ou System.out.println peuvent

    prendre plusieurs arguments séparés par des +...

    for (int i = 0; i < 10; i = i++)

    System.out.println

    ("le arre de " + i + " est " + (i * i));

    • l'assoiation des + s'e�etue de gauhe à droite.

    entre deux valeurs numériques, + garde le sens de �addition�.

    int i = 2;

    System.out.println(i + i); // affihe 4.

    System.out,println(i + " " + i) // affihe 2 2

    System.out,println(i + i + " " + i) // affihe 4 2

    Programmation en Java 8

  • • il existe un type String pour les haînes de aratères.

    + est l'opérateur de onaténation des haînes. on peut onaténer

    une haîne et une valeur numérique, onvertie dans e as en String.

    String s = "ab";

    System.out.println(s); // affihe "ab"

    s = s + "def";

    System.out.println(s); // affihe "abdef"

    s = s + 42;

    System.out.println(s); // affihe "abdef42"

    // et.

    • un argument numérique de println sera onverti en String

    (String est une lasse et les haînes sont des objets, sens à préiser).

    Programmation en Java 9

  • 1.4. Hiérarhie des types de base et onversions

    • boolean (true, false)

    • byte (8 bits, signé)

    • har (16 bits, non signé) (i.e. jeu de aratères étendu)

    • short (16 bits, signé)

    • int (32 bits, signé)

    • long (64 bits signé)

    • float

    • double

    Programmation en Java 10

  • • les onversions vers un type plus petit doivent toujours être expliites.

    /* erreur à la ompilation

    * int x = 1;

    * har = 'a' + x; // 'a' promu en int et

    * // somme en int, pas har

    */

    /* orret. d vaut 'b' */

    int x = 1;

    har d = (har) ('a' + x); // somme onvertie en har.

    Programmation en Java 11

  • /* erreur à la ompilation. 2.5f n'est pas dans

    * les valeurs du type int :

    * int x = 2.5f;

    */

    /* orret. x vaut l'arrondi 2 */

    int x = (int) 2.5f;

    • les onversions véri�ables dès la ompilation sont inutiles :

    /* orret : la valeur 'b' assignée à peut être

    * pré-alulée dès la ompilation, et ette valeur

    * reste dans les limites du type har */

    har e = 'a' + 1;

    Programmation en Java 12

  • • ++ et �- opèrent sans onversions :

    har = 'a';

    ++;

    /* vaut 'b' */

    har d = 'a';

    /* erreur ! d promu en int, d + 1 en int

    * d = d + 1;

    */

    /* orret */

    d = (har) d + 1;

    Programmation en Java 13

  • 2. Objets, Classes et Référenes

    2.1. Des strutures de C aux lasses de Java

    • objet ≡ une généralisation de la notion de struture en C.

    • omme une struture C, un objet

    � enapsule des données désignées par des noms de hamps,

    � est réé suivant un ertain modèle dé�ni à l'avane.

    modèle d'objet ≡ lasse de et objet.

    objets d'une lasse ≡ instanes de ette lasse.

    • un programme Java est suite de délarations de lasses.

    Programmation en Java 14

  • // fihier exemple.

    // delaration d'un nouveau type de struture

    strut point2D { // modele de struture a deux hamps

    int abs; // de type int, indefinis par defaut

    int ord;

    };

    // fontion prinipale du fihier (lanee a l'exeution)

    int main(int arg, har *argv[℄) {

    strut point2D *p; // delaration de pointeur

    // vers strut point2D

    p = mallo(sizeof(strut point2D)); // alloation, stokage de

    // l'adresse allouee dans p

    (*p).abs = 42; // a

    es aux hamps via p

    (*p).ord = 10;

    free(p);

    return 0;

    }

    Programmation en Java 15

  • // fihier Exemple.java (meme nom que la lasse prinipale)

    // delaration d'une nouvelle lasse Point2D

    lass Point2D { // modele d'objet a deux hamps

    int abs; // de type int, valeurs par defaut 0

    int ord;

    }// delaration de la lasse prinipale du fihier

    publi lass Exemple {

    // "fontion" prinipale du fihier (lanee a l'exeution)

    publi stati void main(String[℄ args) {

    Point2D p; // delaration d'une referene (pointeur)

    // vers les objets de la lasse Point2D

    p = new Point2D(); // reation d'une instane de Point2D

    // stokage de son adresse dans p

    p.abs = 42; // a

    es aux hamps de l'objet via

    p.ord = 10; // la referene p.

    }

    }

    Programmation en Java 16

  • • les valeurs de hamps sont nulles à la réation d'un objet,

    sauf si l'on spéi�e expliitement d'autres valeurs :

    lass Point2D {

    int abs = 10; // valeur par defaut pour haque instane ree

    int ord; // valeur nulle a la reation

    }

    Programmation en Java 17

  • 2.2. Les référenes

    • référene en Java :

    � variable pouvant ontenir l'adresse-mémoire d'un objet

    � similaire à un pointeur vers struture de C, mais

    sans la notation * pour l'a

    ès aux hamps.

    • la lasse des objets sur lesquels pourra pointer une référene

    est spéi�ée par sa délaration:

    nom de lasse nom de référene;

    Point2D p;

    (auun objet réé, p est pour l'instant de valeur indé�nie).

    • on peut donner à une référene la valeur nulle : p = null;.

    Programmation en Java 18

  • 2.3. Création et référenement des instanes

    • réation d'une instane via new + nom de lasse :

    Point2D p; // p de valeur indefinie

    p = new Point2D(); // alloation d'un objet en memoire,

    // retour de son adresse, stokage de

    // ette adresse dans p

    // p referene/designe/pointe a present vers l'objet ree

    p.abs = 42; // a

    es aux hamps de l'objet

    p.ord = 10; // via la referene p.

    Programmation en Java 19

  • • deux référenes peuvent référener le même objet :

    Point2D p, q;

    p = new Point2D(); // nouvel objet, referene par p

    q = p; // p et q referenent a present le meme objet

    p.abs = 42; // a

    es a l'objet via p

    q.ord = 10; // a

    es au meme objet via q

    System.out.println(" p.abs = " + p.abs); // 42

    System.out.println(" p.ord = " + p.ord); // 10

    System.out.println(" q.abs = " + q.abs); // 42

    System.out.println(" q.ord = " + q.ord); // 10

    Programmation en Java 20

  • • une même référene peut pointer vers plusieurs objets au ours du temps :

    Point2D p = new Point2D(); // une 1ere instane reee

    p = new Point2D(); // une 2nde instane reee

    La 1ère instane réée est dé�nitivement perdue.

    • pas de fuite de mémoire : les objets qui ne sont plus référenés seront

    t�t ou tard e�aés de la mémoire ("garbage olleting" automatique).

    Programmation en Java 21

  • • les hamps d'un objet peuvent être de type référene :

    lass Point2D {

    int abs; // valeurs par defaut : 0

    int ord;

    }

    lass Segment {

    Point2D debut; // valeurs par defaut : null

    Point2D fin;

    }la réation d'un segment ne rée pas ses extrémités :

    il faut deux new supplémentaires par segment...

    Programmation en Java 22

  • Segment s = new Segment();

    // pour l'instant, s.debut et s.fin valent null.

    // reation des extremites et ablage :

    Point2D p1 = new Point2D();

    Point2D p2 = new Point2D();

    s.debut = p1; // s.debut et p1 designent le meme objet

    s.fin = p2; // s.fin et p2 designent le meme objet

    // reation direte des extremites :

    Segment t = new Segment();

    t.debut = new Point2D();

    t.fin = new Point2D();

    Programmation en Java 23

  • • on peut forer la réation des extrémités via l'initialisation des hamps :

    lass Segment {

    Point2D debut = new Point2D(); // (re)-evalues à haque

    Point2D fin = new Point2D(); // reation de segment.

    }//...

    Segment s = new Segment(); // un segment et deux points rees !

    Segment t = new Segment(); // un segment et deux points rees !

    // et.

    Programmation en Java 24

  • 2.4. Remarques

    • on onfond souvent objet et référene vers objet :

    � "l'objet référené par p", ou

    � "l'objet p"

    � "le point 2D p"

    • une référene ontient en fait plus d'information qu'un pointeur :

    Point2D p = new Point2D();

    System.out.println(p);

    a�he e.g. Point2D�defa1a (lasse + adresse).

    Programmation en Java 25

  • 3. Initialisation d'Objets : les Construteurs

    3.1. Délarations de onstruteurs

    • onstruteur ≡ ode d'initialisation plaé dans une délaration de lasse.

    e ode peut être appelé au moment de la réation d'une instane.

    • haque onstruteur porte le même nom que la lasse.

    il peut avoir des paramètres.

    lass Point2D {

    int abs;

    int ord;

    Point2D() {} // onstruteur sans arguments

    Point2D(int x, int y) { // onstruteur a deux arguments

    abs = x; ord = y;

    }

    }

    Programmation en Java 26

  • • l'appel d'un onstruteur ne peut se faire qu'ave un new, au moment

    de la réation d'une nouvelle instane :

    Point2D p = new Point2D(); // appel du 1er onstruteur

    Point2D q = new Point2D(42, 10); // appel du 2nd.

    • new Point2D(42, 10) :

    1. réation (new) d'une nouvelle instane de Point2D

    2. exéution de Point2D(int x, int y)

    ave passage par valeur x ← 42, y ← 10, et

    abs et ord désignant les hamps de l'objet réé en (1).

    3. retour d'une référene vers l'objet réé.

    Programmation en Java 27

  • lass Point2D {

    int abs;

    int ord;

    Point2D() {}

    Point2D(int x, int y) {

    abs = x;

    ord = y;

    }

    }

    • odes équivalents :

    � Point2D p = new Point2D();

    p.abs = 42;

    p.ord = 10;

    � Point2D p = new Point2D(42, 10);

    Programmation en Java 28

  • 3.2. Construteur par défaut et délarations multiples

    • sans onstruteurs délarés, la lasse est munie impliitement d'un

    onstruteur par défaut (pas d'arguments, orps vide ne faisant rien).

    lass Point2D {

    int abs, ord;

    }est équivalent à

    lass Point2D {

    int abs, ord;

    Point2D() {} // pas d'arguments, et ne faisant rien.

    }(d'ou le new Point2D() dans les exemples préédents)

    Programmation en Java 29

  • • signature de onstruteur ≡ suite des types de ses paramètres.• on peut délarer autant de onstruteurs que l'on veut, pourvu

    que leurs signatures soient distintes :

    lass Point2D {

    int abs;

    int ord;

    Point2D () {} // en () - et a delarer

    Point2D (int x, int y) { // en (int,int)

    abs = x; ord = y

    }Point2D (Point2D p) { // en (Point2D)

    abs = p.abs; ord = p.ord; // opie des hamps du point

    } // passe en parametre

    }

    Programmation en Java 30

  • • Un onstruteur peut en appeler un autre par this(...) en

    1ère instrution (pas néessairement unique) de e onstruteur.

    lass Segment {

    Point2D debut;

    Point2D fin;

    Segment() {

    this(0,0,0,0); // appel du onstruteur

    // en (int,int,int,int)

    // ... et eventuellement, autres instrutions

    }Segment(int x1, int y1, int x2, int y2) {

    debut = new Point2D(x1, y1);

    fin = new Point2D(x2, y2);

    }

    }

    Programmation en Java 31

  • 4. Modi�ations d'objets : les méthodes

    4.1. Délarations de méthodes

    • méthode ≡ ode plaé dans une délaration de lasse,

    permettant la modi�ation des hamps de ses instanes

    lass Point2D {

    int abs;

    int ord; // eventuellement des onstruteurs

    // exemples de methodes :

    void assigner(int x, int y) { abs = x; ord = y; }

    void translater(int dx, int dy) {

    abs = abs + dx;

    ord = ord + dy;

    }

    }

    Programmation en Java 32

  • 4.2. Invoations de méthodes

    • l'exéution d'une méthode se fait toujours relativement à un objet,

    via une référene : on dit que la méthode est invoquée sur l'objet.

    Point2D p = new Point2D();

    p.assigner(42,10);

    p.translater(20,20);

    • p.assigner(42, 10) :

    exéution de assigner(int x, int y)

    ave passage par valeur x ← 42, y ← 10,

    où dans le ode de la méthode,

    abs et ord désignant les hamps de l'objet référené par p.

    Programmation en Java 33

  • • une méthode peut renvoyer une valeur :

    lass Point2D {

    // ... hamps abs, ord, onstruteurs ...

    Point2D loner() {

    Point2D lone = new Point2D();

    lone.abs = abs; // les hamps abs et ord de l'objet

    lone.ord = ord; // ourant sont opies dans le lone

    return lone;

    }

    }// ... et dans une autre partie du programme :

    Point2D p = new Point2D(42,10);

    Point2D q = p.loner(); // q est a present une opie de p

    Programmation en Java 34

  • • une méthode peut invoquer une autre méthode (voire elle-même) :

    lass Point2D {

    // ... hamps abs, ord, onstruteurs ...

    void assigner(int x, int y) {

    abs = x;

    ord = y;

    }void reinitialiser() {

    assigner(0,0); // invoquee sur l'objet ourant

    }

    }// ... et dans une autre partie du programme :

    Point2D p = new Point2D(42,10);

    p.reinitialiser(); // equivalent a : p.assigner(0,0)

    Programmation en Java 35

  • • un onstruteur peut invoquer une méthode :

    lass Point2D {

    int abs;

    int ord;

    Point2D() {}

    Point2D(int x, int y) {

    assigner(x,y); // invoquee sur l'objet qui vient

    } // d'etre ree par new.

    void assigner(int x, int y) {

    abs = x;

    ord = y;

    }

    }

    Programmation en Java 36

  • 4.3. Surharge de noms de méthodes

    • signature de méthode ≡ suite des types de ses paramètres.

    • deux méthodes peuvent porter le même nom à ondition que leurs

    signatures soient distintes. le nom de méthode est dit surhargé.

    • lors de l'invoation, l'implémentation hoisie sera elle qui orrespond

    à la suite des types des arguments fournis...

    Programmation en Java 37

  • lass Point2D {

    int abs;

    int ord;

    // ... onstruteurs ...

    void assigner(int x, int y) {

    abs = x;

    ord = y;

    }void assigner(Point2D p) {

    abs = p.abs;

    ord = p.ord;

    }void assigner() {

    abs = 0;

    ord = 0;

    }

    }

    Programmation en Java 38

  • • ...e qui permet aussi d'érire :

    lass Point2D {

    int abs;

    int ord;

    // ... onstruteurs ...

    void assigner(int x, int y) {

    abs = x;

    ord = y;

    }void assigner(Point2D p) {

    assigner(p.abs, p.ord);

    }void assigner() {

    assigner(0,0);

    }

    }où les deux dernières méthodes en (Point2D) et en () appellent

    la première en (int, int).

    Programmation en Java 39

  • 4.4. Référene à l'objet ourant : this

    • this sans arguments dans une méthode ≡ une référene vers l'objet

    sur lequel ette méthode est invoquée.

    • this sans arguments dans un onstruteur ≡ une référene vers l'objet

    qui vient d'être réé par new.

    lass Point2D {

    //... l'eriture suivante est usuelle :

    Point2D(int abs, int ord) {

    this.abs = abs; this.ord = ord;

    }void set (int abs, int ord) {

    this.abs = abs; this.ord = ord;

    }

    }

    Programmation en Java 40

  • 4.5. Champs vs méthodes et masquage de hamps

    • tout hamp, onstruteur ou méthode préédé du mot-lef private

    est ina

    essible à l'extérieur de sa lasse.

    • en pratique, on privilégie les invoations de méthodes, en délarant souvent

    tous les hamps privés :

    lass Point2D {

    private int abs; // representation interne des donnees,

    private int ord; // invisible depuis l'exterieur.

    // onstruteurs + methodes d'a

    es aux hamps

    ...

    }... et les noms abs et ord deviennent inonnus à l'extérieur de la lasse

    Point2D : il faut passer par les méthodes pour a

    éder aux hamps.

    Programmation en Java 41

  • 4.6. Classe des points, version �nale

    lass Point2D {

    // hamps prives

    private int abs;

    private int ord;

    // onstruteurs

    Point2D() {}

    Point2D(int abs, int ord) {

    this.abs = abs;

    this.ord = ord;

    }// ...

    Programmation en Java 42

  • // methodes d'a

    es en leture : nom standard = getChamp

    int getAbs() {

    return abs;

    }int getOrd() {

    return ord;

    }// ...

    Programmation en Java 43

  • // methodes d'a

    es en leture : nom standard = setChamp

    void setAbs(int abs) {

    this.abs = abs;

    }void setOrd(int ord) {

    this.ord = ord;

    }void set(int abs, int ord) {

    this.abs = abs;

    this.ord = ord;

    }void set(Point2D p) {

    this.set(p.abs, p.ord) // this faultatif, mais ourant

    }

    }Programmation en Java 44

  • 4.7. Conlusion

    • une délaration de lasse ontient :

    � des hamps servant au stokage des données internes de ses instanes,

    � du ode d'initialisation plaé dans des onstruteurs, permettant

    l'initialisation automatique des hamps lors de la réation d'instanes,

    � du ode de gestion des données stokées dans les instanes de ette

    lasse, plaés dans des méthodes, permettant de modi�er les données

    internes d'un objet.

    Programmation en Java 45

  • • en pratique, les hamps sont:

    � ina

    essibles (private),

    � initialisés via les onstruteurs,

    � modi�és via les méthodes.

    i.e. l'utilisateur n'a a priori auune onnaissane de la

    représentation interne des données, mais seulement de

    l'e�et de l'invoation de tel ou tel onstruteur ou méthode.

    Programmation en Java 46

  • PARTIE II - Héritage

    Programmation en Java 47

  • 5. Extensions de lasses

    5.1. Prinipe de l'extension de Classe

    • extension de lasse ≡ permet de dé�nir une nouvelle lasse

    � à partir d'une lasse déjà érite,

    � en réupérant les implémentations de ses méthodes,

    � en modi�ant éventuellement ertaines d'entre elles,

    � en ajoutant éventuellement d'autres hamps et méthodes

    • objetifs :

    � réutiliser du ode déjà érit,

    � adapter une lasse générique à un besoin partiulier,

    � érire plusieurs variantes d'une même lasse, en érivant une seule fois

    le ode ommun à ses variantes.

    Programmation en Java 48

  • 5.2. Syntaxe de l'extension

    lass Point2D {

    int abs, ord;

    void affiher() {

    System.out.println (abs + " " + ord);

    }

    }... variante par extension (extends) : points olorés.

    lass Point2DColore extends Point2D {

    int ol;

    void affiherCouleur() {

    System.out.println (ol);

    }

    }

    Programmation en Java 49

  • Point2DColore p = new Point2DColore();

    p.abs = 10;

    p.ord = 42;

    p.ol = 255;

    p.affiher(); // affihe 10 42

    p.affiherCouleur(); // affihe 255

    les instanes de Point2DColore disposent de tous les hamps et

    méthodes délarés dans la lasse Point2D :

    � la lasse Point2DColore hérite de es hamps et méthodes.

    terminologie pour les liens de parenté :

    � Point2DColore est une extension/une lasse héritìere de Point2D

    � Point2D est une lasse parente/un anêtre de Point2DColore

    Programmation en Java 50

  • 5.3. Redé�nitions de méthodes

    • Une extension peut redé�nir ertaines des méthodes de sa lasse parente :

    lass Point2D {

    int abs, ord;

    void affiher() { // anienne implementation

    System.out.println (abs + " " + ord);

    }

    }

    lass Point2DColore extends Point2D {

    int ol;

    void affiher() { // nouvelle implementation

    System.out.println (abs + " " + ord + " " + ol);

    }

    }

    Programmation en Java 51

  • l'implémentation invoquée pour une instane donnée sera toujours

    elle de sa lasse :

    Point2D p = new Point2D()

    p.abs = 23;

    p.ord = 37

    p.affiher(); // invoque l'implementation de

    // la lasse Point2D : "23 17"

    Point2DColore p = new Point2DColore();

    p.abs = 10;

    p.ord = 42;

    p.ol = 255;

    p.affiher(); // invoque l'implementation de

    // la lasse Point2DColore : "10 42 255"

    Programmation en Java 52

  • • Les méthodes de nouvelles signatures ajoutées à une extension

    sont onsidérées omme nouvelles :

    lass Point2D {

    int abs, ord;

    // methode set en (int, int)

    void set(int abs, int ord) {

    this.abs = abs; this.ord = ord;

    }

    }

    lass Point2DColore extends Point2D {

    int ol;

    // nouvelle methode set en (int, int, int)

    void set(int abs, int ord, int ol) {

    set(abs, ord); // invoation du set en (int, int), herite.

    this.ol = ol;

    }

    }

    Programmation en Java 53

  • 5.4. A

    ès aux aniennes implémentations : super

    • lorsqu'une méthode est redé�nie par une extension, son anienne

    implémentation reste a

    essible via super. + nom de méthode :

    lass Point2D {

    int abs, ord;

    void affiher() { System.out.println (abs + " " + ord); }

    }

    lass Point2DColore extends Point2D {

    int ol;

    void affiher() { // nouvelle implementation

    super.affiher(); // appel de l'anienne, puis

    System.out.println (ol); // affihage supplementaire.

    }

    }

    Programmation en Java 54

  • 5.5. Appel impliite du onstruteur en () de la lasse parente

    • par défaut, l'éxéution d'un onstruteur de Point2DColore est

    préédée de elle du onstruteur en () de sa lasse parente.

    lass Point2D {

    int abs, ord;

    Point2D() { System.out.println ("Point2D !"); }

    }

    lass Point2DColore extends Point2D {

    int ol;

    Point2DColore() {

    // appel impliite de Point2D() avant l'instrution qui

    // suit : new Point2DColore() affihe "Point2D !", puis

    System.out.println ("Point2DColore !"); }

    }...

    Point2DColore p = new Point2DColore();

    // affihe "Point2D !", puis "Point2DColore !"

    Programmation en Java 55

  • • dans e as, un onstruteur en () doit être dé�ni dans la lasse parente.

    l'erreur suivante est lassique :

    lass Point2D {

    int abs, ord; // pas de onstruteur en () ?!...

    Point2D(int abs,int ord) {

    this.abs = abs;

    this.ord = ord;

    }

    }

    lass Point2DColore extends Point2D {

    int ol;

    Point2DColore (int ol) { this.ol = ol }

    }// erreur de ompilation ! le onstruteur de Point2DColore

    // appelle impliitement Point2D(){}... non implemente.

    Programmation en Java 56

  • 5.6. Appel expliite d'un autre onstruteur

    • un onstruteur de Point2DColore peut demander expliitement l'appel

    d'un autre onstruteur que elui en () de sa lasse parente, via

    � this (...) (.f. Partie I)

    qui appelle le onstruteur de la même lasse spéi�é par les types

    des arguments.

    � super (...)

    qui appelle le onstruteur de la lasse parente spéi�é par les types

    des arguments.

    • dans les deux as, l'appel doit être la première instrution du onstruteur,

    et ette forme d'appel n'est pas renouvelable.

    Programmation en Java 57

  • lass Point2D {

    int abs, ord; // valeurs nulles par defaut

    Point2D() {}

    Point2D(int abs,int ord) {

    this.abs = abs;

    this.ord = ord;

    }

    }

    lass Point2DColore extends Point2D {

    int ol;

    Point2DColore() {} // appel impliite de Point2D()

    Point2DColore(int ol) {

    this(0, 0, ol) // appel de Point2DColore(int, int, int)

    }Point2DColore(int abs, int ord, int ol) {

    super (abs, ord); // appel de Point2D(int, int)

    this.ol = ol;

    }

    }

    Programmation en Java 58

  • 5.7. Héritage et masquage

    • Les hamps masqués (par private) d'une lasse parente

    ne sont pas hérités par ses extensions � ils sont ina

    essibles

    à l'extérieur de la lasse parente...

    • ...mais es hamps existent dans les instanes de l'extension,

    même s'ils sont ina

    essibles dans l'extension elle-même.

    • ...et les méthodes de la lasse parente héritées par l'extension

    ontinuent à a

    éder librement à es hamps (puisqu'elles

    les �voient� depuis la lasse parente).

    Programmation en Java 59

  • lass Point2D {

    private int abs, ord; // abs et ord existeront mais seront masques

    int getAbs() { // dans les heritiers

    return abs;

    } // les hamps abs et ord sont

    int getOrd() { // visibles dans ette lasse

    return ord;

    }void set(int abs, int ord) {

    this.abs = abs; this.ord = ord;

    }

    }

    lass Point2DColore extends Point2D {

    private int ol;

    int getCol() {

    return ol;

    }void set(int abs, int ord, int ol) {

    set(abs, ord); // invoation du set en (int,int) qui, depuis

    this.ol = ol; // sa lasse, a

    ede aux hamps masques

    }

    }

    Programmation en Java 60

  • Point2DColore p = new Point2DColore();

    p.set (10, 42, 255);

    int i = p.getAbs(); // 10

    int j = p.getOrd(); // 42

    int = p.getCol(); // 255

    • les expressions p.abs ou p.ord sont inompilables, même si

    tout point oloré dispose bien de es deux hamps.

    • les méthodes getAbs, getOrd sont héritées par Point2DColore. elles sont

    implémentées dans Point2D, don a

    èdent librement aux deux hamps

    depuis leur lasse.

    • la nouvelle méthode set invoque une implémentation de set héritée de

    Point2D qui a

    ède librement aux deux hamps depuis sa lasse.

    Programmation en Java 61

  • • les onstruteurs d'une lasse ou ses méthodes peuvent également être

    délarés private (plus rare).

    • les règles sont les mêmes qu'ave les hamps (non hérités, a

    essibles

    indiretement via les implémentations héritées).

    Programmation en Java 62

  • 5.8. Extensions multiples et extensions d'extensions

    • une même lasse peut avoir un nombre arbitraire d'extensions.

    • toute extension de lasse peut elle-même être étendue.• restritions pour super.+ méthode et super(...) : une lasse

    ne peut a

    éder qu'à l'implémentation (héritée ou non) d'un

    onstruteur ou d'une méthode de son anêtre immédiat :

    on ne peut pas érire super.super...

    Programmation en Java 63

  • lass Point2D {

    private int abs, ord;

    ...

    }

    lass Point2DColore extends Point2D {

    private int ol; // un hamp de plus...

    ...

    }

    lass Point2DColoreNomme extends Point2DColore {

    private har nom; // enore un hamp de plus...

    ...

    } // et..

    // Point2D est parente de Point2DColore et de Point2DColoreNomme

    // Point2DColore est parente de Point2DColoreNomme

    Programmation en Java 64

  • • hiérarhie de lasses ≡ une lasse, et l'ensemble de ses

    desendants (direts ou indirets)

    • une lasse peut avoir plusieurs lasses anêtres (lasse parente, lasse

    parente de ette lasse parente, et.) par onvention, les anêtres d'une

    lasse inluent la lasse elle-même.

    • une lasse prédé�nie est impliitement anêtre de toutes les autres :

    la lasse Objet.

    • un programme java se onçoit en général en onevant un ensemble de

    hiérarhies de lasses (lasses génériques, spéialisations de es lasses,

    spéialisations des spéialisations...)

    Programmation en Java 65

  • PARTIE III - Classes Abstraites

    Programmation en Java 66

  • 6. Notion de lasse abstraite

    • lasse abstraite ≡ lasse inomplète dont ertaines parties restent à érire :

    � non instantiable (pas de new possible) mais elle peut ontenir

    des hamps, des onstruteurs et des méthodes,

    � elle peut mentionner des noms de méthodes non enore implémentées,

    appelées méthodes abstraites,

    � une lasse abstraite est uniquement destinée à être étendue en lasses

    onrètes (instantiables), qui implémenteront les parties manquantes.

    • objetif : toujours le même, érire une seule fois les éléments ommuns à

    toutes les extensions, érire ensuite les spéialisations onrètes.

    Programmation en Java 67

  • 7. Délaration, extension de lasse abstraite - un exemple

    • on souhaite délarer une lasse abstraite permettant de représenter

    des formes géométriques, sans préision de leur nature exate (erle,

    retangle, arré . . . ).

    • toute forme est dé�nie relativement à un ertain point de référene

    (deux hamps x et y ommuns à toutes les formes).

    • toute forme doit pouvoir a�her sa desription (au moins les valeurs

    des hamps x et y).

    • toute forme o

    upe une ertaine surfae... qui ne peut se aluler

    qu'en onnaissant la nature exate de ette forme.

    Programmation en Java 68

  • abstrat lass Forme { // "abstrat", i.e. abstraite

    private int x, y; // hamps ommuns

    Forme() {} // onstruteurs

    Forme(int x, int y) {

    this.x = x;

    this.y = y;

    }int getX() { return x; } // a

    esseurs pour les

    int getY() { return y; } // hamps ommuns

    void setXY(int x, int y) {

    this.x = x;

    this.y = y;

    }void affiher() {

    System.out.println("base : " + x + "," + y);

    }// methode abstraite : a implementer par les

    // heritiers onrets de ette lasse abstraite.

    abstrat double surfae(); // pas d'implementation.

    }

    Programmation en Java 69

  • lass Retangle extends Forme {

    private int hauteur, largeur; // hamps supplementaires

    Retangle() {} // onstruteurs

    Retangle(int x, int y, int hauteur, int largeur) {

    super(x,y); // init. des hamps de Forme

    this.hauteur = hauteur; this.largeur = largeur;

    }int getHauteur() { return hauteur; } // a

    esseurs pour les

    int getLargeur() { return largeur; } // hamps ajoutes

    void setDimension(int hauteur, int largeur) {

    this.hauteur = hauteur; this.largeur = largeur;

    }void affiher() { // redefinition de l'affihage

    super.affiher(); // appel de l'implementation de Forme,

    System.out.println("hauteur : " + hauteur);

    System.out.println("largeur : " + largeur);

    }double surfae () { // implementation de la methode

    return hauteur * largueur; // abstraite de Forme.

    }

    }

    Programmation en Java 70

  • lass Cerle extends Forme {

    private int rayon; // hamp supplementaire

    Cerle() {} // onstruteurs

    Cerle(int x, int y, int rayon) {

    super(x,y);

    this.rayon = rayon;

    }int getRayon() { // a

    esseurs pour le

    return rayon; // hamp ajoute

    }void setRayon(int rayon) {

    this.rayon = rayon;

    }void affiher() { // redefinition de l'affihage

    super.affiher(); // appel de l'implementation de Forme,

    System.out.println ("rayon : " + r);

    }double surfae () { // implementation de la methode

    return Math.PI * rayon * rayon; // abstraite de Forme.

    }

    }

    Programmation en Java 71

  • • règles d'héritage, de onstrutions, d'a

    essibilité des hamps, et. :

    les mêmes que pour une extension de lasse onrète.

    • toute lasse abstraite ou onrète peut être étendue en une lasse

    onrète ou abstraite, toutes les extensions sont extensibles.

    • une extension abstraite peut laisser abstraites une partie des méthodes

    abstraite de sa lasse parente et en introduire de nouvelles.

    • seule ontrainte sur les extensions :

    toute extension onrète doit fournir une implémentation de haque

    méthode enore abstraite dans sa lasse parente (héritée ou non).

    Programmation en Java 72

  • PARTIE IV - Liaison dynamique

    Programmation en Java 73

  • Programmation en Java 74

  • 8. Conversions de référenes

    8.1. Conversion asendante de référene

    • Règle de délaration libre : on peut délarer des référenes vers

    n'importe quelle lasse.

    Forme f; // legal, meme si Forme est abstraite

    • Regle de onversion asendante : on peut référener un objet

    par toute référene vers l'une de ses lasses anêtres.

    Forme f;

    Cerle = new Cerle();

    Retangle r = new Retangle();

    f = ; // onversion "asendante" de

    // en une referene vers Forme... legal.

    f = r; // onversion "asendante" de r... legal.

    Programmation en Java 75

  • 8.2. Conversion desendante

    • Règle de onversion desendante : on peut onvertir expliitement une

    référene dans la diretion opposée, pourvu que la référene-ible soit vers

    une lasse anêtre de elle de l'objet.

    Forme f = new Cerle();

    Cerle = (Cerle) f; // valide

    // Retangle r = (Retangle) f;// erreur d'exeution !!

    f = new Carre() // ou Carre est une extension de Retangle

    Retangle r = (Retangle) f; // valide : Retangle est anetre de Carre.

    • es onversions ne hangent pas les lasses des objets, mais simplement

    le type des référenes qui servent à les manipuler.

    Programmation en Java 76

  • 8.3. Véri�ation de la validité d'une onversion

    • on peut véri�er (à l'exéution seulement) la validité d'une

    onversion desendante à l'aide de instaneof :

    Forme f = Math.random() > .5 ? new Cerle() : new Carre ();

    Retangle r = null;

    if (f instane of Retangle) r = (Retangle) f;

    • f instaneof Retangle vaut true si et seulement si Retangle est

    anêtre de la lasse de f � i.e. si la onversion (Retangle) f est valide.

    • instaneof ne permet pas de déterminer la lasse exate d'un objet, mais

    simplement de véri�er si une lasse est anêtre de elle-i. en pratique,

    son usage est réservé à la véri�ation de validité d'une onversion.

    Programmation en Java 77

  • 8.4. A

    essibilité des noms suivant le type des référenes

    • lorsqu'un objet est référené par une référene vers une ertaine lasse,

    seuls les hamps et méthodes de ette lasse (non masqués, dans la lasse

    ou hérités) sont a

    essibles et invoables via ette référene.

    Forme f = new Cerle();

    f.affiher(); // legal : affiher est dans la lasse Forme

    // f.setRayon(10); // erreur !! la lasse Forme ne ontient pas

    // ette methode, definie dans Cerle.

    Cerle = (Cerle) f; // desente vers Cerle

    .setRayon(10); // legal.

    Programmation en Java 78

  • 9. Liaison dynamique

    9.1. Règle de liaison dynamique � la règle entrale du langage

    lorsqu'une méthode est invoquée sur une référene, l'implémentation

    hoisie est toujours elle de la lasse de l'objet référené (érite dans

    sa lasse, ou héritée), quel que soit le type de ette référene.

    • exemple :

    Cerle = new Cerle(); Forme f = ;

    f.affiher(); // dans les deux as, l'implementation

    .affiher(); // hoisie est elle de Cerle.

    f = Math.random() > .5 ? new Cerle() : new Retangle ();

    f.affiher(); // implementation hoisie a l'exeution !

    affiher() sera lié (assoié) dynamiquement (à l'exéution) à une

    ertaine implémentation, suivant la lasse de l'objet.

    Programmation en Java 79

  • // exemple preedent, tres simplifie :

    abstrat lass Forme {

    abstrat void affiher();

    }

    lass Retangle extends Forme {

    void affiher() { System.out.println("Retangle"); }

    }

    lass Cerle extends Forme {

    void affiher() { System.out.println("Cerle");

    }Retangle r = new Retangle();

    Forme f = r;

    f.affiher(); // affihe "Retangle", omme r.affiher()

    Cerle = new Cerle();

    f = ;

    f.affiher(); // affihe "Cerle", omme .affiher()

    Forme[℄ dessin = {new Retangle(), new Carre()};

    for (int i = 0; i < 2; i++) dessin[i℄.affiher();

    // affihe "Retangle" puis "Cerle"

    Programmation en Java 80

  • // autre exemple : type de donnees abstrait

    abstrat lass Pile {

    abstrat int pop();

    abstrat void push(int n);

    abstrat boolean isEmpty();

    }... // ailleurs : lasse(s) onrete(s) etendant Pile...

    // implementation(s) par tableau, liste hainee, et.

    ... // et quelque part dans une autre lasse :

    void m(Pile p) {

    if (!p.isEmpty()) { // invoquera les methodes de la

    int n = p.pop(); // lasse (onrete) de p.

    // et.

    } // la methode est dite "polymorphe" : elle a

    epte des

    } // objets de lasses differentes, en ne se servant que

    // de leurs noms de methodes ommuns.

    Programmation en Java 81

  • 9.2. Règle de hoix d'implémentation des méthodes

    • Si l'on invoque un nom de méthode sur des arguments de

    types U1,. . . , Un, la méthode hoisie sera elle de signature

    T1,. . . , Tn, où haque Ti est le plus prohe anêtre de Ui.

    lass A {...}

    lass B extends A {...}

    lass C extends B {...}

    lass D extends C {...}

    // ... dans une lasse E : surharge du nom de methode m

    void m(A a) {...}

    void m(C ) {...}

    // ... et ailleurs :

    D d = new D(); C = d; B b = d; A a = d;

    e.m(d); // methode invoquee : elle en (C)

    e.m(); // methode invoquee : elle en (C)

    e.m(b); // methode invoquee : elle en (A)

    e.m(a); // methode invoquee : elle en (A)

    Programmation en Java 82

  • PARTIE V - Interfaes

    Programmation en Java 83

  • 10. Notion d'interfae

    • interfae ≡ similaire à une lasse abstraite, mais enore plus inomplète.

    une simple liste de noms de méthodes.

    interfae Deplaable {

    Point2D getPosition();

    void setPosition(Point2D p);

    void alignerAve(Deplaable d);

    }

    • une lasse implémente une interfae lorsqu' elle implémente haune

    de ses méthodes.

    • une lasse ne peut être l'extension que d'une seule lasse, mais elle peut

    implémenter plusieurs interfaes.

    Programmation en Java 84

  • interfae Deplaable {

    Point2D getPosition();

    void setPosition(Point2D p);

    void alignerAve(Deplaable d);

    }

    lass Segment implements Deplaable {

    Point2D debut, fin;

    // onstruteurs, et.

    publi Point2D getPosition() {

    return debut;

    }publi void setPosition(Point2D p) {

    debut.translater(p);

    fin.translater(p);

    }publi void alignerAve(Deplaable d) {

    setPosition(d.getPosition());

    }

    }

    Programmation en Java 85

  • interfae Deplaable {

    Point2D getPosition();

    void setPosition(Point2D p);

    void alignerAve(Deplaable d);

    }// ...

    abstrat lass Forme implements Deplaable {

    // hamps x, y, onstruteurs, et.

    publi Point2D getPosition() {

    return new Point2D(getX(), getY())

    }publi void setPosition(Point2D p) {

    setX(p.getX()); setY(p.getY());

    }publi void alignerAve(Deplaable d) {

    setPosition(d.getPosition());

    }

    }

    lass Cerle extends Forme { ... } // implemente impliitement Deplaable par heritage.

    Programmation en Java 86

  • • pas de lien de parenté entre Segment et les héritiers onrets de Forme...

    mais "pont" réé entre toutes es lasses : une interfae ommune.

    • alignerAve a

    epte tout objet dont la lasse implémente Deplaable.

    tous es objets sont référençables par des référenes de type Deplaable.

    Deplaable d = new Cerle(); // onversion asendante

    Deplaable e = new Segment(); // onversion asendante

    d.alignerAve(e); // legal

    e.alignerAve(d); // legal

    Segment s = new Segment(); // onversion asendante

    Cerle = new Retangle(); // de en referene vers

    s.alignerAve(); // Deplaable. legal.

    Programmation en Java 87

  • • une lasse peut implémenter plusieurs interfaes :

    lass B extends C implements I, J, K {...}

    • une lasse abstraite peut être marquée omme implémentant une interfae,

    mais ne pas implémenter toutes ses méthodes.

    • les interfaes sont extensibles, et même multi-extensibles

    interfae I { ... }

    interfae J { ... }

    interfae K extends I, J { ... }

    • on peut ajouter des hamps - impliitement final et stati.

    Programmation en Java 88

  • Annexe - Compléments

    Programmation en Java 89

  • 11. Finalité de lasses, hamps, méthodes variables

    • final ≡ plus modi�able, en plusieurs sens.

    • final lass C {...} : la lasse C n'est plus extensible.

    • lass C { final int x; ... }

    le hamp x doit être initialisé dès la réation, et ne sera plus modi�able.

    • lass C {... final int m() {...} }

    le méthode m() ne pourra pas être rédé�nie dans les extensions de C.

    • final permet de réer des objets non-mutables.

    • variables en final ≡ onst de C.

    Programmation en Java 90

  • 12. Champs et méthodes statiques

    • hamp statique ≡ hamp partagé par toutes les instanes d'une lasse.

    • un seul exemplaire de e hamp en mémoire. reservé dès le lanement

    du programme, et indépendamment de toute réation d'objet.

    lass Point2D {

    stati int nbreInstanesCrees = 0; // ompteur ommun a tous les points.

    int abs, ord;

    Point2D() { nbreInstanesCrees++; }

    Point2D(int abs, int ord) {

    this();

    this.abs = abs;

    this.ord = ord;

    }

    }

    Programmation en Java 91

  • • a

    ès à un hamp statique :

    � via le nom de la lasse

    � ou via une référene initialisée dont la lasse voit e hamp

    // lanement du programme.

    System.out.println(Point2D.nbreInstanesCrees); // affihe 0

    Point2D p = new Point2D(); // premiere instane reee.

    System.out.println(Point2D.nbreInstanesCrees); // affihe 1

    // et.

    Programmation en Java 92

  • • méthode statique ≡ une méthode qui n'a

    ède qu'à des hamps statiques.

    invoable indépendamment de tout objet.

    lass Point2D {

    stati int nbreInstanesCrees = 0; // ompteur ommun

    int abs, ord; // a tous les points.

    Point2D() { nbreInstanesCrees++; }

    stati void affiherNbreInstanesCrees() {

    System.out.println(nbreInstanesCrees);

    }

    }

    • invoation via le nom de la lasse (ou une référene initialisée) :

    Point2D.affiherNbreInstanesCrees();

    Programmation en Java 93

  • 12.1. Appliations des hamps et méthodes statiques

    • �librairie� de fontions utilitaires (omme en C)

    lass Divers {

    stati final double Pi = 3.1415927;

    stati int max(int x, int y) {

    return x > y ? x : y;

    }stati int min(int x, int y) {

    return x < y ? x : y;

    }private Divers() {} // unique onstruteur prive...

    } // don lasse non instantiable,

    // et non extensible !

    Programmation en Java 94

  • • dé�nitions de onstantes, et même onstantes d'objets :

    lass Couleur {

    stati final

    BLANC = new Couleur (255,255,255),

    NOIR = new Couleur (0,0,0);

    final int r, v, b; // hamps non mutables

    Couleur() {

    this (0,0,0);

    }Couleur (int r, int v, int b) {

    this.r = r;

    this.v = v;

    this.b = b;

    }

    }

    Programmation en Java 95

  • • lasse singleton : une, et une seule instane.

    lass Elvis {

    private stati final THE_KING = new Elvis ();

    private Elvis() {} // prive... pas d'autre new possible

    // pas d'extension possible.

    stati Elvis getInstane() {

    return THE_KING;

    }

    }

    Programmation en Java 96

  • • lasse à deux éléments et seulement deux :

    lass Boolean {

    private final boolean b;

    private stati final // deux instanes, et pas plus

    Boolean TRUE = new Boolean (true),

    FALSE = new Boolean (false);

    private Boolean (Boolean b) {

    this.b = b;

    }stati Boolean getInstane(boolean b) { //"usine statique"

    return b ? TRUE : FALSE;

    }

    }

    Programmation en Java 97