PO3T Programmation orientée objet
Séance 4
Polymorphisme, interface et
classe abstraite
Sébastien Combéfis, Quentin Lurkin lundi 12 octobre 2015
Ce(tte) œuvre est mise à disposition selon les termes de la Licence Creative Commons
Attribution – Pas d’Utilisation Commerciale – Pas de Modification 4.0 International.
Rappels
Extension d’une classe existante par héritage
Une sous-classe étend une super-classe
Relation is-a
Différence composition/héritage
Redéfinition de méthode
Modification d’une méthode existante de la super-classe
Accès aux membres de la super-classe depuis la sous-classe
Visibilité des membres (public/private/protected)
3
Objectifs
Polymorphisme des objets
Référence polymorphique
Résolution dynamique des appels
Interface et classe abstraite
Interface publique
Classe et méthode abstraite
4
Polymorphisme
Type d’un objet
Un objet peut avoir plusieurs types
Une instance d’une sous-classe est aussi une de la super-classe
Méthodes accessibles sont celles de toute la hiérarchie
Car les méthodes héritées sont les méthodes accessibles
Une référence polymorphique peut être convertie
Conversion vers n’importe quel type compatible
6
Représenter un point du plan
Point dans le plan en coordonnées entières
Méthode translate qui renvoie un nouveau point translaté
1 public class Point
2 {
3 private readonly int x, y;
4
5 public int X { get { return x; } }
6 public int Y { get { return y; } }
7
8 public Point (int x, int y)
9 {
10 this.x = x;
11 this.y = y;
12 }
13
14 public Point translate (int dx , int dy)
15 {
16 return new Point (x + dx , y + dy);
17 }
18 }
7
Point coloré
Extension de la classe Point
Ajout d’une variable d’instance pour stocker la couleur
Appel du constructeur de la super-classe pour stocker x et y
Et code spécifique pour stocker colour
1 public class ColouredPoint : Point
2 {
3 private readonly Color colour;
4
5 public Color Colour { get { return colour; } }
6
7 public ColouredPoint (int x, int y, Color colour) : base (x, y)
8 {
9 this.colour = colour;
10 }
11 }
8
Hiérarchie de classe
Établissement d’une hiérarchie de classe
Plusieurs classes liées par des relations d’héritage
Point
ColouredPoint
9
Redéfinition de méthode
Redéfinition d’une méthode
Remplacement de la version de la super-classe
Représentation en chaine de caractères d’un point coloré
Se base sur la méthode déjà présente dans la super-classe
1 public class ColouredPoint
2 {
3 // ...
4
5 public override string ToString ()
6 {
7 return string.Format("{0} [colour ={1}]", base.ToString (),
colour);
8 }
9 }
10
Référence polymorphique (1)
Redéfinition d’une méthode
Remplacement de la version de la super-classe
Représentation en chaine de caractères d’un point coloré
Se base sur la méthode déjà présente dans la super-classe
1 public class Program
2 {
3 public static void Main ( string [] args)
4 {
5 Point p = new Point (12, -5);
6 Console .WriteLine (p);
7
8 ColouredPoint q = new ColouredPoint (7, 5, Color.FromArgb
(255 , 0, 0));
9 Console .WriteLine (q);
10 }
11 }
11
Référence polymorphique (2)
p
Point
Die
12
x
int
−5
y
int
q
ColouredPoint
ColouredPoint
7
x
int
5
y
int
[255, 0, 0]
colour
Color
Point
- int x
- int y
+ Point Translate(int, int)
+ string ToString()
ColouredPoint
- Color colour
+ string ToString()
12
Référence polymorphique (3)
Tester le type dynamique d’une référence
Test de la relation is-a
Opérateur de test de la compatibilité de type
Variable contient une référence vers un objet d’un type donné
1 Console .WriteLine ((p is Point) + " / " + (p is ColouredPoint ));
2 Console .WriteLine ((q is Point) + " / " + (q is ColouredPoint ));
True / False
True / True
13
Polymorphisme (1)
Différence type d’une variable et celui de l’objet référencé
Type statique et type dynamique
Une variable peut avoir plusieurs types par polymorphisme
Ces différents types doivent être compatibles
1 ColouredPoint p1;
2 Point p2;
3
4 // Type statique ColouredPoint et type dynamique ColouredPoint
5 p1 = new ColouredPoint (-1, 2, Color.FromArgb (0, 255, 0));
6
7 // Type statique Point et type dynamique ColouredPoint
8 p2 = new ColouredPoint (8, 1, Color.FromArgb (0, 0, 255));
14
Polymorphisme (2)
Type statique
Type utilisé lors de la déclaration de la variable
Déterminé une fois pour toute à la déclaration
Limite les références qui pourront être stockées
Uniquement pour les langages typés statiquement
Type dynamique
Type de l’objet référencé par la variable
Déterminé lors de l’exécution
Peut changer en cours d’exécution
15
Conversion implicite
Objet d’une sous-classe dans variable d’une super-classe
Conversion implicite de la référence
1 ColouredPoint p;
2 Point q;
3
4 p = new ColouredPoint (7, 5, Color.FromArgb (255 , 0, 0));
5 q = p;
6 Console .WriteLine (q);
(7, 5) [colour=Color [A=255 , R=255 , G=0, B=0]]
16
Conversion explicite
Variable d’une super-classe vers objet d’une sous-classe
Conversion explicite de la référence
1 Point p;
2 ColouredPoint q;
3
4 p = new ColouredPoint (7, 5, Color.FromArgb (255 , 0, 0));
5 if (p is ColouredPoint )
6 {
7 q = ( ColouredPoint ) p;
8 Console .WriteLine (q);
9 }
(7, 5) [colour=Color [A=255 , R=255 , G=0, B=0]]
17
Type compatible
Deux types compatibles sont liés par une relation de filiation
Sous-classe compatible avec super-classe
Attention, la compatibilité est unidirectionnelle
Dans le sens de la relation is-a
Conversions si type dynamique de b compatible avec A
Implicite : A a = b;
Explicite : A a = (A) b;
18
Résolution des appels de méthode (1)
Le type statique détermine les méthodes accessibles
Les seules méthodes accessibles sont celles du type statique
La méthode effectivement appelée dépend du type dynamique
En cas de redéfinition, la méthode de la sous-classe est appelée
Résolution en deux étapes
Méthodes accessibles vérifiées à la compilation
Méthode appelée décidée à l’exécution
19
Résolution des appels de méthode (2)
Méthode sous-classe non accessible
Car le type statique est celui de la super-classe
1 Point p = new ColouredPoint (7, 5, Color.FromArgb (255 , 0, 0));
2
3 Console .WriteLine (p.Colour);
error CS1061: Type ‘Cours4.Point ’ does not contain a definition
for ‘Colour ’ and no extension method ‘Colour ’ of type ‘Cours4.
Point ’ could be found. Are you missing an assembly reference?
20
Résolution des appels de méthode (3)
Méthode redéfinie dans sous-classe appelée
Même si type statique de la variable est de la super-classe
1 Point p = new ColouredPoint (7, 5, Color.FromArgb (255 , 0, 0));
2
3 Console .WriteLine (p.ToString ());
(7, 5) [colour=Color [A=255 , R=255 , G=0, B=0]]
21
Résolution des appels de méthode (4)
Méthode héritée accessible dans la sous-classe
La méthode translate est héritée par la sous-classe
Le type de retour de la méthode reste néanmoins Point
Comment faire pour renvoyer un ColouredPoint ?
1 ColouredPoint p = new ColouredPoint (7, 5, Color.FromArgb (255 , 0,
0));
2
3 Console .WriteLine (p.Translate (1, -1));
(8, 4)
22
Et en Python... (1)
1 class Point:
2 def __init__(self , x, y):
3 self.__x = x
4 self.__y = y
5
6 @property
7 def x(self):
8 return self.__x
9
10 @property
11 def y(self):
12 return self.__y
13
14 def translate(self , dx , dy):
15 return Point(self.__x + dx , self.__y + dy)
16
17 def __str__(self):
18 return ’({}, {}) ’.format(self.__x , self.__y)
19
20 p = Point (12, -5)
21 print(p)
(12, -5)
23
Et en Python... (2)
1 class ColouredPoint (Point):
2 def __init__(self , x, y, colour):
3 Point.__init__(self , x, y)
4 self.__colour = colour
5
6 @property
7 def colour(self):
8 return self.__colour
9
10 def __str__(self):
11 return ’{} [colour ={}] ’.format(Point.__str__(self), self.
__colour)
12
13 q = ColouredPoint (7, 5, ’red ’)
14 print(q)
15
16 print(isinstance(q, Point))
(7, 5) [colour=red]
True
24
Et en Java... (1)
1 public class Point
2 {
3 private final int x, y;
4
5 public Point (int x, int y)
6 {
7 this.x = x;
8 this.y = y;
9 }
10
11 public int getX () { return x; }
12 public int getY () { return y; }
13
14 public Point translate (int dx , int dy)
15 {
16 return new Point (x + dx , y + dy);
17 }
18
19 @Override
20 public String toString ()
21 {
22 return String.format ("(%d, %d)", x, y);
23 }
24 }
25
Et en Java... (2)
1 class ColouredPoint extends Point
2 {
3 private final Color colour;
4
5 public ColouredPoint (int x, int y, Color colour)
6 {
7 super (x, y);
8 this.colour = colour;
9 }
10
11 @Override
12 public String toString ()
13 {
14 return String.format ("%s [colour =%s]", super.toString (),
colour);
15 }
16 }
1 ColouredPoint q = new ColouredPoint (7, 5, Color.RED);
2 System.out.println (q);
3
4 System.out.println (q instanceof ColouredPoint );
26
Et en PHP... (1)
1 <?php
2 class Point
3 {
4 private $x , $y;
5
6 public function __construct ($x , $y)
7 {
8 $this ->x = $x;
9 $this ->y = $y;
10 }
11
12 public function translate ($dx , $dy)
13 {
14 return new Point ($this ->x + $dx , $this ->y + $dy);
15 }
16
17 public function __toString ()
18 {
19 return sprintf ("(%d, %d)", $this ->x, $this ->y);
20 }
21 }
22
23 $p = new Point (12, -5);
24 echo $p;
25 ?>
27
Et en PHP... (2)
1 <?php
2 class ColouredPoint extends Point
3 {
4 private $colour;
5
6 public function __construct ($x , $y , $colour)
7 {
8 parent :: __construct ($x , $y);
9 $this ->colour = $colour;
10 }
11
12 public function __toString ()
13 {
14 return sprintf ("%s (%s)", parent :: __toString (), $this ->
colour);
15 }
16 }
17
18 $q = new ColouredPoint (7, 5, "red");
19 echo $q;
20 ?>
28
Interface et classe abstraite
Interface
Une interface ne contient que des entêtes de méthode
Permet de définir un contrat avec un utilisateur
1 public interface Complex
2 {
3 // Partie réelle du complexe
4 public double real ();
5
6 // Partie imaginaire du complexe
7 public double imag ();
8
9 // Module du complexe
10 public double abs ();
11
12 // Argument du complexe
13 public double arg ();
14 }
30
Relation d’implémentation
Une classe peut implémenter une interface
Doit fournir un corps pour toutes les méthodes de l’interface
1 public class CartesianComplex implements Complex
2 {
3 private final double a, b;
4
5 // a + bi
6 public CartesianComplex (double a, double b)
7 {
8 this.a = a;
9 this.b = b;
10 }
11
12 public double real () { return a; }
13 public double imag () { return b; }
14 public double abs () { return Math.sqrt (a * a + b * b); }
15 public double arg () { return Math.acos (a / abs ()); }
16 }
31
Polymorphisme (1)
Plusieurs classes peuvent implémenter la même interface
Permet du polymorphisme comme l’héritage
1 class PolarComplex implements Complex
2 {
3 private final double r, theta;
4
5 public PolarComplex (double r, double theta)
6 {
7 this.r = r;
8 this.theta = theta;
9 }
10
11 public double real () { return r * Math.cos (theta); }
12 public double imag () { return r * Math.sin (theta); }
13 public double abs () { return r; }
14 public double arg () { return theta; }
15 }
32
Polymorphisme (2)
Somme de nombres complexes facilitée par polymorphisme
Il suffit de passer par les méthodes de l’interface
1 List <Complex > list = new ArrayList <Complex >();
2 list.add (new CartesianComplex (2, -1));
3 list.add (new PolarComplex (2, Math.PI / 2));
4 list.add (new CartesianComplex (-1, 1));
5
6 double a = 0;
7 double b = 0;
8 for (Complex c : list)
9 {
10 a += c.real ();
11 b += c.imag ();
12 }
13 Complex sum = new CartesianComplex (a, b);
14 System.out.println (sum);
1 ,000000 + 2 ,000000 i
33
Implémentation multiple
Une classe peut implémenter plusieurs interfaces
Ce qui lève la limitation des langages sans héritage multiple
La relation implements est également une relation is-a
Shape Drawable
Square
34
Classe abstraite (1)
Intermédiaire entre l’interface et la classe concrète
Certaines méthodes communes peuvent être implémentées
1 public abstract class Complex
2 {
3 public abstract double real ();
4 public abstract double imag ();
5
6 public double abs ()
7 {
8 double a = real ();
9 double b = imag ();
10 return Math.sqrt (a * a + b * b);
11 }
12
13 public double arg ()
14 {
15 return Math.acos (real () / abs ());
16 }
17 }
35
Classe abstraite (2)
Une classe abstraite est étendue en classe concrète
Il faut définir le corps des méthodes abstraites
1 class PolarComplex extends Complex
2 {
3 private final double r, theta;
4
5 public PolarComplex (double r, double theta)
6 {
7 this.r = r;
8 this.theta = theta;
9 }
10
11 public double real () { return r * Math.cos (theta); }
12 public double imag () { return r * Math.sin (theta); }
13
14 @Override public double abs () { return r; }
15 @Override public double arg () { return theta; }
16 }
36
Hiérarchie de classe
Une interface est une classe abstraite pure
Et ne contenant pas de constructeur, ni de variables d’instance
Une sous-classe d’une classe abstraite peut être abstraite
Si elle ne fournit pas de corps à toutes les méthodes abstraites
Permet d’éviter de la duplication de code
En rassemblant les membres communs dans la super-classe
37
Circuit logique
Porte logique (1)
Implémentation d’un circuit de portes logiques
Une porte logique générique possède n entrées et une sortie
Connectée à une entrée d’une autre porte logique en sortie
1 public abstract class Gate
2 {
3 private boolean [] in;
4 protected boolean out;
5 private String name;
6 private Gate outgate;
7 private int outnum;
8
9 public Gate ( String n, int nbIn)
10 {
11 name = n;
12 in = new boolean [nbIn ];
13 }
39
Porte logique (2)
1 public void setIn (int num , boolean state)
2 {
3 in[num] = state;
4 boolean oldout = out;
5
6 update ();
7
8 if (outgate != null && out != oldout)
9 {
10 outgate.setIn (outnum , out);
11 }
12 }
13
14 public void connect (Gate g, int in)
15 {
16 outgate = g;
17 outnum = in;
18 }
19
20 public int getInNb ()
21 {
22 return in.length;
23 }
40
Porte logique (3)
1 public boolean getIn (int num)
2 {
3 return in[num];
4 }
5
6 public String toString ()
7 {
8 StringBuffer buff = new StringBuffer ();
9 buff.append (name).append (" :ntIn :t");
10 for (int i = 0; i < in.length; i++)
11 {
12 buff.append (in[i] ? ’1’ : ’0’).append (’ ’);
13 }
14 buff.append ("ntOut :t").append (out ? ’1’ : ’0’);
15 return buff.append ("n").toString ();
16 }
17
18 // Méthode de mise à jour de l’état de la porte logique
19 // et de mise à jour de l’entrée du voisin
20 protected abstract void update ();
21 }
41
Porte AND et porte NOT
1 public class AndGate extends Gate
2 {
3 public AndGate (String name)
4 {
5 super (name , 2);
6 }
7
8 @Override
9 protected void update ()
10 {
11 out = getIn (0) && getIn (1);
12 }
13 }
14
15 public class NotGate extends Gate
16 {
17 public NotGate (String name)
18 {
19 super (name , 1);
20 }
21
22 @Override
23 protected void update ()
24 {
25 out = ! getIn (0);
26 }
27 }
42
Circuit logique
1 Gate g1 = new OrGate ("g1");
2 Gate g2 = new NotGate ("g2");
3
4 g1.connect (g2 , 0);
5
6 g1.setIn (1, true);
7 g2.setIn (0, true);
8
9 System.out.println (g1);
10 System.out.println (g2);
g1 :
In : 0 1
Out : 1
g2 :
In : 1
Out : 0
43
Crédits
https://www.flickr.com/photos/caochopp/5714454341
https://www.flickr.com/photos/foxrosser/2984981024
https://www.flickr.com/photos/summerwind/191444024
44

Polymorphisme, interface et classe abstraite

  • 1.
    PO3T Programmation orientéeobjet Séance 4 Polymorphisme, interface et classe abstraite Sébastien Combéfis, Quentin Lurkin lundi 12 octobre 2015
  • 2.
    Ce(tte) œuvre estmise à disposition selon les termes de la Licence Creative Commons Attribution – Pas d’Utilisation Commerciale – Pas de Modification 4.0 International.
  • 3.
    Rappels Extension d’une classeexistante par héritage Une sous-classe étend une super-classe Relation is-a Différence composition/héritage Redéfinition de méthode Modification d’une méthode existante de la super-classe Accès aux membres de la super-classe depuis la sous-classe Visibilité des membres (public/private/protected) 3
  • 4.
    Objectifs Polymorphisme des objets Référencepolymorphique Résolution dynamique des appels Interface et classe abstraite Interface publique Classe et méthode abstraite 4
  • 5.
  • 6.
    Type d’un objet Unobjet peut avoir plusieurs types Une instance d’une sous-classe est aussi une de la super-classe Méthodes accessibles sont celles de toute la hiérarchie Car les méthodes héritées sont les méthodes accessibles Une référence polymorphique peut être convertie Conversion vers n’importe quel type compatible 6
  • 7.
    Représenter un pointdu plan Point dans le plan en coordonnées entières Méthode translate qui renvoie un nouveau point translaté 1 public class Point 2 { 3 private readonly int x, y; 4 5 public int X { get { return x; } } 6 public int Y { get { return y; } } 7 8 public Point (int x, int y) 9 { 10 this.x = x; 11 this.y = y; 12 } 13 14 public Point translate (int dx , int dy) 15 { 16 return new Point (x + dx , y + dy); 17 } 18 } 7
  • 8.
    Point coloré Extension dela classe Point Ajout d’une variable d’instance pour stocker la couleur Appel du constructeur de la super-classe pour stocker x et y Et code spécifique pour stocker colour 1 public class ColouredPoint : Point 2 { 3 private readonly Color colour; 4 5 public Color Colour { get { return colour; } } 6 7 public ColouredPoint (int x, int y, Color colour) : base (x, y) 8 { 9 this.colour = colour; 10 } 11 } 8
  • 9.
    Hiérarchie de classe Établissementd’une hiérarchie de classe Plusieurs classes liées par des relations d’héritage Point ColouredPoint 9
  • 10.
    Redéfinition de méthode Redéfinitiond’une méthode Remplacement de la version de la super-classe Représentation en chaine de caractères d’un point coloré Se base sur la méthode déjà présente dans la super-classe 1 public class ColouredPoint 2 { 3 // ... 4 5 public override string ToString () 6 { 7 return string.Format("{0} [colour ={1}]", base.ToString (), colour); 8 } 9 } 10
  • 11.
    Référence polymorphique (1) Redéfinitiond’une méthode Remplacement de la version de la super-classe Représentation en chaine de caractères d’un point coloré Se base sur la méthode déjà présente dans la super-classe 1 public class Program 2 { 3 public static void Main ( string [] args) 4 { 5 Point p = new Point (12, -5); 6 Console .WriteLine (p); 7 8 ColouredPoint q = new ColouredPoint (7, 5, Color.FromArgb (255 , 0, 0)); 9 Console .WriteLine (q); 10 } 11 } 11
  • 12.
    Référence polymorphique (2) p Point Die 12 x int −5 y int q ColouredPoint ColouredPoint 7 x int 5 y int [255,0, 0] colour Color Point - int x - int y + Point Translate(int, int) + string ToString() ColouredPoint - Color colour + string ToString() 12
  • 13.
    Référence polymorphique (3) Testerle type dynamique d’une référence Test de la relation is-a Opérateur de test de la compatibilité de type Variable contient une référence vers un objet d’un type donné 1 Console .WriteLine ((p is Point) + " / " + (p is ColouredPoint )); 2 Console .WriteLine ((q is Point) + " / " + (q is ColouredPoint )); True / False True / True 13
  • 14.
    Polymorphisme (1) Différence typed’une variable et celui de l’objet référencé Type statique et type dynamique Une variable peut avoir plusieurs types par polymorphisme Ces différents types doivent être compatibles 1 ColouredPoint p1; 2 Point p2; 3 4 // Type statique ColouredPoint et type dynamique ColouredPoint 5 p1 = new ColouredPoint (-1, 2, Color.FromArgb (0, 255, 0)); 6 7 // Type statique Point et type dynamique ColouredPoint 8 p2 = new ColouredPoint (8, 1, Color.FromArgb (0, 0, 255)); 14
  • 15.
    Polymorphisme (2) Type statique Typeutilisé lors de la déclaration de la variable Déterminé une fois pour toute à la déclaration Limite les références qui pourront être stockées Uniquement pour les langages typés statiquement Type dynamique Type de l’objet référencé par la variable Déterminé lors de l’exécution Peut changer en cours d’exécution 15
  • 16.
    Conversion implicite Objet d’unesous-classe dans variable d’une super-classe Conversion implicite de la référence 1 ColouredPoint p; 2 Point q; 3 4 p = new ColouredPoint (7, 5, Color.FromArgb (255 , 0, 0)); 5 q = p; 6 Console .WriteLine (q); (7, 5) [colour=Color [A=255 , R=255 , G=0, B=0]] 16
  • 17.
    Conversion explicite Variable d’unesuper-classe vers objet d’une sous-classe Conversion explicite de la référence 1 Point p; 2 ColouredPoint q; 3 4 p = new ColouredPoint (7, 5, Color.FromArgb (255 , 0, 0)); 5 if (p is ColouredPoint ) 6 { 7 q = ( ColouredPoint ) p; 8 Console .WriteLine (q); 9 } (7, 5) [colour=Color [A=255 , R=255 , G=0, B=0]] 17
  • 18.
    Type compatible Deux typescompatibles sont liés par une relation de filiation Sous-classe compatible avec super-classe Attention, la compatibilité est unidirectionnelle Dans le sens de la relation is-a Conversions si type dynamique de b compatible avec A Implicite : A a = b; Explicite : A a = (A) b; 18
  • 19.
    Résolution des appelsde méthode (1) Le type statique détermine les méthodes accessibles Les seules méthodes accessibles sont celles du type statique La méthode effectivement appelée dépend du type dynamique En cas de redéfinition, la méthode de la sous-classe est appelée Résolution en deux étapes Méthodes accessibles vérifiées à la compilation Méthode appelée décidée à l’exécution 19
  • 20.
    Résolution des appelsde méthode (2) Méthode sous-classe non accessible Car le type statique est celui de la super-classe 1 Point p = new ColouredPoint (7, 5, Color.FromArgb (255 , 0, 0)); 2 3 Console .WriteLine (p.Colour); error CS1061: Type ‘Cours4.Point ’ does not contain a definition for ‘Colour ’ and no extension method ‘Colour ’ of type ‘Cours4. Point ’ could be found. Are you missing an assembly reference? 20
  • 21.
    Résolution des appelsde méthode (3) Méthode redéfinie dans sous-classe appelée Même si type statique de la variable est de la super-classe 1 Point p = new ColouredPoint (7, 5, Color.FromArgb (255 , 0, 0)); 2 3 Console .WriteLine (p.ToString ()); (7, 5) [colour=Color [A=255 , R=255 , G=0, B=0]] 21
  • 22.
    Résolution des appelsde méthode (4) Méthode héritée accessible dans la sous-classe La méthode translate est héritée par la sous-classe Le type de retour de la méthode reste néanmoins Point Comment faire pour renvoyer un ColouredPoint ? 1 ColouredPoint p = new ColouredPoint (7, 5, Color.FromArgb (255 , 0, 0)); 2 3 Console .WriteLine (p.Translate (1, -1)); (8, 4) 22
  • 23.
    Et en Python...(1) 1 class Point: 2 def __init__(self , x, y): 3 self.__x = x 4 self.__y = y 5 6 @property 7 def x(self): 8 return self.__x 9 10 @property 11 def y(self): 12 return self.__y 13 14 def translate(self , dx , dy): 15 return Point(self.__x + dx , self.__y + dy) 16 17 def __str__(self): 18 return ’({}, {}) ’.format(self.__x , self.__y) 19 20 p = Point (12, -5) 21 print(p) (12, -5) 23
  • 24.
    Et en Python...(2) 1 class ColouredPoint (Point): 2 def __init__(self , x, y, colour): 3 Point.__init__(self , x, y) 4 self.__colour = colour 5 6 @property 7 def colour(self): 8 return self.__colour 9 10 def __str__(self): 11 return ’{} [colour ={}] ’.format(Point.__str__(self), self. __colour) 12 13 q = ColouredPoint (7, 5, ’red ’) 14 print(q) 15 16 print(isinstance(q, Point)) (7, 5) [colour=red] True 24
  • 25.
    Et en Java...(1) 1 public class Point 2 { 3 private final int x, y; 4 5 public Point (int x, int y) 6 { 7 this.x = x; 8 this.y = y; 9 } 10 11 public int getX () { return x; } 12 public int getY () { return y; } 13 14 public Point translate (int dx , int dy) 15 { 16 return new Point (x + dx , y + dy); 17 } 18 19 @Override 20 public String toString () 21 { 22 return String.format ("(%d, %d)", x, y); 23 } 24 } 25
  • 26.
    Et en Java...(2) 1 class ColouredPoint extends Point 2 { 3 private final Color colour; 4 5 public ColouredPoint (int x, int y, Color colour) 6 { 7 super (x, y); 8 this.colour = colour; 9 } 10 11 @Override 12 public String toString () 13 { 14 return String.format ("%s [colour =%s]", super.toString (), colour); 15 } 16 } 1 ColouredPoint q = new ColouredPoint (7, 5, Color.RED); 2 System.out.println (q); 3 4 System.out.println (q instanceof ColouredPoint ); 26
  • 27.
    Et en PHP...(1) 1 <?php 2 class Point 3 { 4 private $x , $y; 5 6 public function __construct ($x , $y) 7 { 8 $this ->x = $x; 9 $this ->y = $y; 10 } 11 12 public function translate ($dx , $dy) 13 { 14 return new Point ($this ->x + $dx , $this ->y + $dy); 15 } 16 17 public function __toString () 18 { 19 return sprintf ("(%d, %d)", $this ->x, $this ->y); 20 } 21 } 22 23 $p = new Point (12, -5); 24 echo $p; 25 ?> 27
  • 28.
    Et en PHP...(2) 1 <?php 2 class ColouredPoint extends Point 3 { 4 private $colour; 5 6 public function __construct ($x , $y , $colour) 7 { 8 parent :: __construct ($x , $y); 9 $this ->colour = $colour; 10 } 11 12 public function __toString () 13 { 14 return sprintf ("%s (%s)", parent :: __toString (), $this -> colour); 15 } 16 } 17 18 $q = new ColouredPoint (7, 5, "red"); 19 echo $q; 20 ?> 28
  • 29.
  • 30.
    Interface Une interface necontient que des entêtes de méthode Permet de définir un contrat avec un utilisateur 1 public interface Complex 2 { 3 // Partie réelle du complexe 4 public double real (); 5 6 // Partie imaginaire du complexe 7 public double imag (); 8 9 // Module du complexe 10 public double abs (); 11 12 // Argument du complexe 13 public double arg (); 14 } 30
  • 31.
    Relation d’implémentation Une classepeut implémenter une interface Doit fournir un corps pour toutes les méthodes de l’interface 1 public class CartesianComplex implements Complex 2 { 3 private final double a, b; 4 5 // a + bi 6 public CartesianComplex (double a, double b) 7 { 8 this.a = a; 9 this.b = b; 10 } 11 12 public double real () { return a; } 13 public double imag () { return b; } 14 public double abs () { return Math.sqrt (a * a + b * b); } 15 public double arg () { return Math.acos (a / abs ()); } 16 } 31
  • 32.
    Polymorphisme (1) Plusieurs classespeuvent implémenter la même interface Permet du polymorphisme comme l’héritage 1 class PolarComplex implements Complex 2 { 3 private final double r, theta; 4 5 public PolarComplex (double r, double theta) 6 { 7 this.r = r; 8 this.theta = theta; 9 } 10 11 public double real () { return r * Math.cos (theta); } 12 public double imag () { return r * Math.sin (theta); } 13 public double abs () { return r; } 14 public double arg () { return theta; } 15 } 32
  • 33.
    Polymorphisme (2) Somme denombres complexes facilitée par polymorphisme Il suffit de passer par les méthodes de l’interface 1 List <Complex > list = new ArrayList <Complex >(); 2 list.add (new CartesianComplex (2, -1)); 3 list.add (new PolarComplex (2, Math.PI / 2)); 4 list.add (new CartesianComplex (-1, 1)); 5 6 double a = 0; 7 double b = 0; 8 for (Complex c : list) 9 { 10 a += c.real (); 11 b += c.imag (); 12 } 13 Complex sum = new CartesianComplex (a, b); 14 System.out.println (sum); 1 ,000000 + 2 ,000000 i 33
  • 34.
    Implémentation multiple Une classepeut implémenter plusieurs interfaces Ce qui lève la limitation des langages sans héritage multiple La relation implements est également une relation is-a Shape Drawable Square 34
  • 35.
    Classe abstraite (1) Intermédiaireentre l’interface et la classe concrète Certaines méthodes communes peuvent être implémentées 1 public abstract class Complex 2 { 3 public abstract double real (); 4 public abstract double imag (); 5 6 public double abs () 7 { 8 double a = real (); 9 double b = imag (); 10 return Math.sqrt (a * a + b * b); 11 } 12 13 public double arg () 14 { 15 return Math.acos (real () / abs ()); 16 } 17 } 35
  • 36.
    Classe abstraite (2) Uneclasse abstraite est étendue en classe concrète Il faut définir le corps des méthodes abstraites 1 class PolarComplex extends Complex 2 { 3 private final double r, theta; 4 5 public PolarComplex (double r, double theta) 6 { 7 this.r = r; 8 this.theta = theta; 9 } 10 11 public double real () { return r * Math.cos (theta); } 12 public double imag () { return r * Math.sin (theta); } 13 14 @Override public double abs () { return r; } 15 @Override public double arg () { return theta; } 16 } 36
  • 37.
    Hiérarchie de classe Uneinterface est une classe abstraite pure Et ne contenant pas de constructeur, ni de variables d’instance Une sous-classe d’une classe abstraite peut être abstraite Si elle ne fournit pas de corps à toutes les méthodes abstraites Permet d’éviter de la duplication de code En rassemblant les membres communs dans la super-classe 37
  • 38.
  • 39.
    Porte logique (1) Implémentationd’un circuit de portes logiques Une porte logique générique possède n entrées et une sortie Connectée à une entrée d’une autre porte logique en sortie 1 public abstract class Gate 2 { 3 private boolean [] in; 4 protected boolean out; 5 private String name; 6 private Gate outgate; 7 private int outnum; 8 9 public Gate ( String n, int nbIn) 10 { 11 name = n; 12 in = new boolean [nbIn ]; 13 } 39
  • 40.
    Porte logique (2) 1public void setIn (int num , boolean state) 2 { 3 in[num] = state; 4 boolean oldout = out; 5 6 update (); 7 8 if (outgate != null && out != oldout) 9 { 10 outgate.setIn (outnum , out); 11 } 12 } 13 14 public void connect (Gate g, int in) 15 { 16 outgate = g; 17 outnum = in; 18 } 19 20 public int getInNb () 21 { 22 return in.length; 23 } 40
  • 41.
    Porte logique (3) 1public boolean getIn (int num) 2 { 3 return in[num]; 4 } 5 6 public String toString () 7 { 8 StringBuffer buff = new StringBuffer (); 9 buff.append (name).append (" :ntIn :t"); 10 for (int i = 0; i < in.length; i++) 11 { 12 buff.append (in[i] ? ’1’ : ’0’).append (’ ’); 13 } 14 buff.append ("ntOut :t").append (out ? ’1’ : ’0’); 15 return buff.append ("n").toString (); 16 } 17 18 // Méthode de mise à jour de l’état de la porte logique 19 // et de mise à jour de l’entrée du voisin 20 protected abstract void update (); 21 } 41
  • 42.
    Porte AND etporte NOT 1 public class AndGate extends Gate 2 { 3 public AndGate (String name) 4 { 5 super (name , 2); 6 } 7 8 @Override 9 protected void update () 10 { 11 out = getIn (0) && getIn (1); 12 } 13 } 14 15 public class NotGate extends Gate 16 { 17 public NotGate (String name) 18 { 19 super (name , 1); 20 } 21 22 @Override 23 protected void update () 24 { 25 out = ! getIn (0); 26 } 27 } 42
  • 43.
    Circuit logique 1 Gateg1 = new OrGate ("g1"); 2 Gate g2 = new NotGate ("g2"); 3 4 g1.connect (g2 , 0); 5 6 g1.setIn (1, true); 7 g2.setIn (0, true); 8 9 System.out.println (g1); 10 System.out.println (g2); g1 : In : 0 1 Out : 1 g2 : In : 1 Out : 0 43
  • 44.