Planche 1

Inf 431 -- Cours 7
Modularité
Programmation


par objets (1/2)


http://jeanjacqueslevy.net
secrétariat de l'enseignement:
Catherine Bensoussan
cb@lix.polytechnique.fr
Aile 00, LIX,
01 69 33 34 67
http://www.enseignement.polytechnique.fr/informatique/IF

Planche 2

Plan


.6@percent
  1. Modularité
  2. Paquetages et espace des noms
  3. Contrôle d'accès

  4. Programmation par objets
  5. Sous-classes et conversions de type

  6. Types disjonctifs et sous-classes

Planche 3

Programmes et abstraction (1/3)

Planche 4

Programmes et abstraction (2/3)

Planche 5

Programmes et abstraction (3/3)

ublicrivateackagemportfs
Planche 6

Modularité en Java (1/4)

Considérons l'exemple des files d'attente.

Interface publique:
FIFO, ajouter et supprimer.

Implémentation privée
public class FIFO {
  private int               debut, fin;
  private boolean           pleine, vide;
  private int[ ]            contenu;

  public FIFO  (int n) {
    debut = 0; fin = 0; pleine = n == 0; vide = true;
    contenu = new int[n];
  }

Planche 7

Modularité en Java (2/4)


public static void ajouter (int x, FIFO f) {
    if (f.pleine)
        throw new Error ("File Pleine.");
    f.contenu[f.fin] = x;
    f.fin = (f.fin + 1) % f.contenu.length;
    f.vide = false; f.pleine = f.fin == f.debut;
  }

public static int supprimer (FIFO f) {
    if (f.vide)
        throw new Error ("File Vide.");
    int res = f.contenu[f.debut];
    f.debut =  (f.debut + 1) % f.contenu.length;
    f.vide = f.fin == f.debut; f.pleine = false;
    return res;
  }

Planche 8

Modularité en Java (3/4)



L'interface public est visible, l'implémentation est opaque.

En Java, le mot-clé
interface a une autre signification. Dans certains langages de programmation (Modula, ML), il y a une distinction entre interfaces et implémentations, permettant la compilation séparée.

Planche 9

Modularité en Java (4/4)


public class FIFO {
  private Liste debut, fin;
  public FIFO (int n) { debut = null; fin = null; }

  public static void ajouter (int x, FIFO f) {
    if (f.fin == null) f.debut = f.fin = new Liste (x);
    else {
      f.fin.suivant = new Liste (x);
      f.fin = f.fin.suivant;
    }
  }

  public static int supprimer (FIFO f) {
    if (f.debut == nullthrow new Error ("File Vide.");
    else {
      int res = f.debut.val;
      if (f.debut == f.fin)  f.debut = f.fin = null;
      else f.debut = f.debut.suivant;
      return res;
    }
  }

Þ Mêmes signatures pour les variables et fonctions publiques dans les deux implémentations (constructeur compris).
Planche 10

Espace des noms (1/4)

Planche 11

Espace des noms (2/4)

Planche 12

Espace des noms (3/4)

Planche 13

Espace des noms (4/4)

Planche 14

Contrôle d'accès (1/2)

Pour les membres d'une classe, il y a 3 types d'accès: Exercice 1 Montrer qu'on accède facilement aux champs ou fonctions des classes compilées dans le même répertoire.

Planche 15

Contrôle d'accès (2/2)

Pour les membres d'un paquetage, il y a 2 types d'accès:
Planche 16

Programmation par objets (1/3)


  modification des modification du
  données programme
programmation    
procédurale changement global changement local
programmation    
par objets changement local changement global
Planche 17

Programmation par objets (2/3)

Un autre argument est souvent avancé par les pro-objets: Mais
Planche 18

Programmation par objets (3/3)

L'argument supplémentaire est celui de la
 
programmation incrémentale
Planche 19

Objets

Les objets sont les instances d'une classe. Ils ont un état (la valeur de leurs champs de données) et un ensemble de méthodes attachées.

Planche 20

Sous-classe et sous-typage (1/6)


class Point {   // ------------------ Version 1
  double x, y;
  static void translation (Point pdouble dx, double dy) {
    p.x = p.x + dx; p.y = p.y + dy;
  }

  static void rotation (Point pdouble theta) {
    double x = p.x * Math.cos(theta) - p.y * Math.sin(theta);
    double y = p.x * Math.sin(theta) + p.y * Math.cos(theta);
    p.x = x; p.y = y;
} }

class PointC extends  Point {
  final static int JAUNE = 0, ROUGE = 1;
  int c;
  PointC (double x0, double y0, int col) { x = x0; y = y0; c = col;}

  public static void main (String[ ] args) {
    PointC p = new PointC(3, 4, JAUNE) ;
    rotation (p, Math.PI/2);
} }

Planche 21

Sous-classe et sous-typage (2/6)


Version 1

ß

Version 2

On change la signature de Rotation pour rendre un Point comme résultat:
Planche 22

Sous-classe et sous-typage (3/6)


class Point {   // ------------------ Version 2
  double x, y;
  static void translation (Point pdouble dx, double dy) {
    p.x = p.x + dx; p.y = p.y + dy;
  }

  static Point rotation (Point pdouble theta) {
    double x = p.x * Math.cos(theta) - p.y * Math.sin(theta);
    double y = p.x * Math.sin(theta) + p.y * Math.cos(theta);
    p.x = x; p.y = y;
    return p;
} }

class PointC extends Point {
  final static int JAUNE = 0, ROUGE = 1;
  int c;
  PointC (double x0, double y0, int col) { x = x0; y = 0; c = col;}

  public static void main (String[ ] args) {
    PointC p = new PointC(3, 4, JAUNE) ;
    p = (PointC) rotation (p, Math.PI/2);  // cast nécessaire
} }

Planche 23

Sous-classe et sous-typage (4/6)


Version 2
et
Version 3
Planche 24

Sous-classe et sous-typage (5/6)


class Point {   // ------------------ Version 3
  double x, y;
  static void translation (Point pdouble dx, double dy) {
    p.x = p.x + dx; p.y = p.y + dy;
  }

  static Point rotation (Point pdouble theta) {
    double x = p.x * Math.cos(theta) - p.y * Math.sin(theta);
    double y = p.x * Math.sin(theta) + p.y * Math.cos(theta);
    return new Point(x, y);
} }

class PointC extends Point {
  final static int JAUNE = 0, ROUGE = 1;
  int c;
  PointC (double x0, double y0, int col) { x = x0; y = 0; c = col;}

  public static void main (String[ ] args) {
    PointC p = new PointC(3, 4, JAUNE) ;
    p = (PointC) rotation (p, Math.PI/2); // lève ClassCastException
} }

Planche 25

Sous-classe et sous-typage (6/6)

L'opérateur + de concaténation appelle toujours la méthode (publique) toString de la classe de son argument. On peut spécialiser cette méthode:
class Point {
  double x, y;
  ...
  public String toString() { return "(" + x + ", " + y + ")"; }
}

class PointC extends Point {
  final static int JAUNE = 0, ROUGE = 1;
  int c;
  ...
  public String toString() { return "(" + x + ", " + y + ", " + c + ")"; }

  public static void main (String[ ] args) {
    PointC p = new PointC(3, 4, JAUNE) ;
    System.out.println (p);
} }

Remarque: System.out.print(x) = System.out.print(x.toString())
Planche 26

Résumé

Planche 27

Contrôle d'accès et sous-classes

Les champs ou méthodes d'une classe peuvent être: Exercice 2 Comment donner un accès public aux objets d'une classe, tout en contrôlant leurs créations, i.e. en interdisant les accès publics aux constructeurs?

Planche 28

Types disjonctifs et classes (1/4)

Programmation récursive simple des ASA:
Données: t terme, e liste d'association de valeurs aux variables.
But: calcul la valeur du terme t dans l'environnement e.
Méthode utilisée: induction structurelle sur les ASA.
static int evaluer (Terme t, Environnement e) {
  switch (t.nature) {
  case ADD: return evaluer (t.a1, e) + evaluer (t.a2, e);
  case SUB: return evaluer (t.a1, e) - evaluer (t.a2, e);
  case MUL: return evaluer (t.a1, e) * evaluer (t.a2, e);
  case DIV: return evaluer (t.a1, e) / evaluer (t.a2, e);
  case CONST: return t.val;
  case VAR: return assoc (t.nom, e);
  defaultthrow new Error ("Erreur dans evaluation");
} }

static int assoc (String s, Environnement e) {
  if (e == nullthrow new Error ("Variable non définie");
  if (e.nom.equals(s)) return e.val;
  else return assoc (s, e.suivant);
}

Planche 29

Types disjonctifs et classes (2/4)

Programmation par objets des ASA:
Une classe abstraite peut contenir quelques champs indéfinis.
abstract class Terme {
  abstract int eval (Environnement e);
  abstract public String toString ();
}

class Add extends Terme {
  Terme a1, a2;
  Add (Terme x, Terme y) {a1 = x; a2 = y; }
  int eval (Environnement e) { return a1.eval(e) + a2.eval(e); }
  public String toString () { return "(" + a1 +  " + " + a2 + ")"; }
}

class Mul extends Terme {
  Terme a1, a2;
  Mul (Terme x, Terme y) {a1 = x; a2 = y; }
  int eval (Environnement e) { return a1.eval(e) * a2.eval(e); }
  public String toString () { return "(" + a1 +  " * " + a2 + ")"; }
}
Planche 30

Types disjonctifs et classes (3/4)


class Const extends Terme {
  int valeur;
  Const (int n) { valeur = n; }
  int eval (Environnement e) { return valeur; }
  public String toString () { return valeur + ""; }
}

class Var extends Terme {
  String nom;
  Var (String s) { nom = s; }
  int eval (Environnement e) { return Environnement.assoc(nom, e); }
  public String toString () { return nom; }
}

class Sub extends Terme {
  Terme a1, a2;
  Sub (Terme x, Terme y) {a1 = x; a2 = y; }
  int eval (Environnement e) { return a1.eval(e) - a2.eval(e); }
  public String toString () { return "(" + a1 +  " - " + a2 + ")"; }
}
Planche 31

Types disjonctifs et classes (4/4)


class Test {
    public static void main (String[ ] args) {
    ...
    Terme t = expression();
    System.out.println (t);
    Environnement e = ... ;
    System.out.println (t.eval(e));
  }
}

Exercice 3 Ecrire la méthode
equals qui teste l'égalité (structurelle) de deux termes.

Exercice 4 Calculer la dérivée d'un terme arithmétique en programmation par objets.

Exercice 5 Ecrire la méthode de belle-impression de termes arithmétiques en programmation par objets.


Planche 32

Procédural ou Objets?


This document was translated from LATEX by HEVEA.