polymorphisme, interface et classe abstraite
TRANSCRIPT
PO3T Programmation orientée objet
Séance 4
Polymorphisme, interface etclasse abstraite
Sébastien Combéfis, Quentin Lurkin lundi 12 octobre 2015
Ce(tte) œuvre est mise à disposition selon les termes de la Licence Creative CommonsAttribution – 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 Point2 {3 private readonly int x, y;45 public int X { get { return x; } }6 public int Y { get { return y; } }78 public Point (int x, int y)9 {
10 this .x = x;11 this .y = y;12 }1314 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 : Point2 {3 private readonly Color colour ;45 public Color Colour { get { return colour ; } }67 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 ColouredPoint2 {3 // ...45 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 Program2 {3 public static void Main ( string [] args)4 {5 Point p = new Point (12 , -5);6 Console . WriteLine (p);78 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 / FalseTrue / 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;34 // Type statique ColouredPoint et type dynamique ColouredPoint5 p1 = new ColouredPoint (-1, 2, Color . FromArgb (0, 255 , 0));67 // Type statique Point et type dynamique ColouredPoint8 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;34 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;34 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));23 Console . WriteLine (p. Colour );
error CS1061 : Type ‘Cours4 .Point ’ does not contain a definitionfor ‘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));23 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));
23 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 = x4 self.__y = y56 @property7 def x(self):8 return self.__x9
10 @property11 def y(self):12 return self.__y1314 def translate (self , dx , dy):15 return Point (self.__x + dx , self.__y + dy)1617 def __str__ (self):18 return ’({} , {}) ’. format (self.__x , self.__y)1920 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 = colour56 @property7 def colour (self):8 return self. __colour9
10 def __str__ (self):11 return ’{} [ colour ={}] ’. format ( Point . __str__ (self), self.
__colour )1213 q = ColouredPoint (7, 5, ’red ’)14 print (q)1516 print ( isinstance (q, Point ))
(7, 5) [ colour =red]True
24
Et en Java... (1)
1 public class Point2 {3 private final int x, y;45 public Point (int x, int y)6 {7 this .x = x;8 this .y = y;9 }
1011 public int getX () { return x; }12 public int getY () { return y; }1314 public Point translate (int dx , int dy)15 {16 return new Point (x + dx , y + dy);17 }1819 @Override20 public String toString ()21 {22 return String . format ("(%d, %d)", x, y);23 }24 }
25
Et en Java... (2)
1 class ColouredPoint extends Point2 {3 private final Color colour ;45 public ColouredPoint (int x, int y, Color colour )6 {7 super (x, y);8 this . colour = colour ;9 }
1011 @Override12 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);34 System .out. println (q instanceof ColouredPoint );
26
Et en PHP... (1)
1 <?php2 class Point3 {4 private $x , $y;56 public function __construct ($x , $y)7 {8 $this ->x = $x;9 $this ->y = $y;
10 }1112 public function translate ($dx , $dy)13 {14 return new Point ($this ->x + $dx , $this ->y + $dy);15 }1617 public function __toString ()18 {19 return sprintf ("(%d, %d)", $this ->x, $this ->y);20 }21 }2223 $p = new Point (12 , -5);24 echo $p;25 ?>
27
Et en PHP... (2)
1 <?php2 class ColouredPoint extends Point3 {4 private $colour ;56 public function __construct ($x , $y , $colour )7 {8 parent :: __construct ($x , $y);9 $this -> colour = $colour ;
10 }1112 public function __toString ()13 {14 return sprintf ("%s (%s)", parent :: __toString () , $this ->
colour );15 }16 }1718 $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 Complex2 {3 // Partie réelle du complexe4 public double real ();56 // Partie imaginaire du complexe7 public double imag ();89 // Module du complexe
10 public double abs ();1112 // Argument du complexe13 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 Complex2 {3 private final double a, b;45 // a + bi6 public CartesianComplex ( double a, double b)7 {8 this .a = a;9 this .b = b;
10 }1112 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 Complex2 {3 private final double r, theta ;45 public PolarComplex ( double r, double theta )6 {7 this .r = r;8 this . theta = theta ;9 }
1011 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));56 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 Complex2 {3 public abstract double real ();4 public abstract double imag ();56 public double abs ()7 {8 double a = real ();9 double b = imag ();
10 return Math .sqrt (a * a + b * b);11 }1213 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 Complex2 {3 private final double r, theta ;45 public PolarComplex ( double r, double theta )6 {7 this .r = r;8 this . theta = theta ;9 }
1011 public double real () { return r * Math .cos ( theta ); }12 public double imag () { return r * Math .sin ( theta ); }1314 @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 Gate2 {3 private boolean [] in;4 protected boolean out;5 private String name;6 private Gate outgate ;7 private int outnum ;89 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;56 update ();78 if ( outgate != null && out != oldout )9 {
10 outgate . setIn (outnum , out);11 }12 }1314 public void connect (Gate g, int in)15 {16 outgate = g;17 outnum = in;18 }1920 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 }56 public String toString ()7 {8 StringBuffer buff = new StringBuffer ();9 buff. append (name). append (" :\n\tIn :\t");
10 for (int i = 0; i < in. length ; i++)11 {12 buff. append (in[i] ? ’1’ : ’0’). append (’ ’);13 }14 buff. append ("\n\tOut :\t"). append (out ? ’1’ : ’0’);15 return buff. append ("\n"). toString ();16 }1718 // Méthode de mise à jour de l’état de la porte logique19 // et de mise à jour de l’ entrée du voisin20 protected abstract void update ();21 }
41
Porte AND et porte NOT
1 public class AndGate extends Gate2 {3 public AndGate ( String name)4 {5 super (name , 2);6 }78 @Override9 protected void update ()
10 {11 out = getIn (0) && getIn (1);12 }13 }1415 public class NotGate extends Gate16 {17 public NotGate ( String name)18 {19 super (name , 1);20 }2122 @Override23 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");34 g1. connect (g2 , 0);56 g1. setIn (1, true );7 g2. setIn (0, true );89 System .out. println (g1);
10 System .out. println (g2);
g1 :In : 0 1Out : 1
g2 :In : 1Out : 0
43
Crédits
https://www.flickr.com/photos/caochopp/5714454341https://www.flickr.com/photos/foxrosser/2984981024https://www.flickr.com/photos/summerwind/191444024
44