Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Notes de cours GEI 442 : STRUCTURES DE DONNÉES ET ALGORITHMES Chapitre 1 : Langage JAVA Partie 4 : Héritage et interfaces Ahmed KHOUMSI GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 1 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Classe dérivée extends : ce mot-clé permet de déclarer qu ’une classe est dérivée d ’une autre classe public class A extends B { ... } A est une sous-classe (ou classe dérivée) de B B est une super-classe (ou classe mère) de B Classe dérivée : - hérite de tous les champs de données de la classe mère - peut ajouter de nouveaux champs de données - hérite de toutes les méthodes de la classe mère elle peut les accepter telles quelles ou les redéfinir - peut définir de nouvelles méthodes Quelques règles : - les méthodes public de la classe mère ne peuvent pas être redéfinies comme étant private dans la classe dérivée - les méthodes de la classe mère qui ne sont pas spécifiées dans la classe dérivée sont héritées sans changement, sauf dans le cas du constructeur (voir plus loin) GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 2 1 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Règles de visibilité, mot-clé protected Un membre d ’une classe C : - qui est public est visible par toutes les autres classes - qui est private n ’est visble par aucune autre classe Si on veut qu ’un membre de C soit visible uniquement par les classes qui dérivent de C, alors on le déclare protected GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 3 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Exemple de classe dérivée On considère la classe Ballon (voir partie 3, page 4) Classe dérivée : Balle = Ballon avec poids public class Balle extends Ballon { // méthode ajoutée public int pese( ) { return poids; } // méthodes redéfinies public void gonfle(int x) { if x > 0 { vol = vol + x; poids = poids + k*x; } } public void degonfle(int x) { if ( (x > 0) && (x <= vol) ) { vol = vol - x; poids = poids - k*x; } } // méthode héritée sans changement : volume( ) // données ajoutées private int poids; private final static int k=2; // donnée héritée : vol; } Remarque : Il faut que vol soit déclarée protected dans la classe Ballon car les méthodes redéfinies utilisent vol GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 4 2 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Constructeur de classe dérivée Si la classe dérivée ne possède pas de constructeur, alors un constructeur sans argument est utilisé par défaut. Celui-ci : (a) appelle le constructeur sans argument de la classe mère pour la partie héritée (b) applique les initialisations par défaut pour les champs de données ajoutés Le point (a) est appliqué même si la classe dérivée possède un constructeur GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 5 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Méthode super Elle permet à la classe dérivée d ’appeler un constructeur de la classe mère La méthode super : - doit être appelée (par la classe dérivée) avec des arguments qui sont compatibles avec un constructeur de la classe mère - ne peut être utilisée que dans la première ligne d ’un constructeur de la classe dérivée Si elle n ’est pas utilisée, alors un appel à super sans argument est automatiquement généré GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 6 3 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Exemple d ’utilisation de la méthode super On reconsidère les classes Ballon et Balle On avait défini deux constructeurs pour la classe Ballon (voir partie 3, page 6) public Ballon( int x ) { vol = x; } public Ballon( ) { vol =0; } On peut définir les trois constructeurs suivants pour la classe Balle public Balle( int x, int y ) { super( x ); // appel de Ballon( x ) poids = y; } public Balle( int x ) { super( x ); poids = 0; } public Balle( ) { super( ); // appel de Ballon( ), inutile poids = 0; } GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 7 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Méthodes finales final : ce mot-clé permet de spécifier qu ’une méthode peut être héritée sans possibilité d ’être redéfinie Exemple : - Dans la classe Ballon : - on peut avoir : public final int volume( ) { return vol; } - si on avait spécifié gonfle et degonfle comme étant final, alors on n ’aurait pas pu les redéfinir dans Balle (voir page 4) - Dans la classe Balle : on peut avoir : public final int pese( ) { return poids; } Rappel : lorsque le mot-clé final est utilisé pour une donnée initialisée, alors cette donnée ne peut plus être modifiée (constante) GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 8 4 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Classes finales Une classe spécifiée final ne peut pas être étendue (héritée) Exemple : si Ballon avait été spécifiée public final class Ballon … alors : - on n ’aurait pas pu définir Balle comme une classe dérivée de Ballon - on aurait dû définir Balle avec tous ses champs, indépendamment de Ballon Remarque : Une classe dont toutes les méthodes sont final n ’est pas forcément final GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 9 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Redéfinition de méthodes dans une classe dérivée On peut redéfinir une méthode en fournissant une nouvelle méthode qui a la même signature (càd même nom et arguments) La nouvelle méthode (de la classe dérivée) : - doit retourner le même type que la méthode d ’origine (de la classe mère) - ne doit pas ajouter de nouvelles exceptions dans la liste throws - peut faire appel à la méthode d ’origine à l ’aide de super Exemple : Classes Ballon et Balle Les méthodes gonfle et degonfle de Balle peuvent être réécrites comme suit : public void gonfle(int x) { if x > 0 { super.gonfle( x ); poids = poids + k*x; } } public void degonfle(int x) { if ( (x > 0) && (x <= vol) ) { super.degonfle( x ); poids = poids - k*x; } } Avec cette nouvelle définition, vol peut être spécifié private au lieu de protected (voir page 4) GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 10 5 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Méthodes et classes abstraites Méthode abstraite : - spécifiée par mot-clé abstract - définie par : - signature et - type retourné - son corps (càd son implantation) : - n ’est pas défini - peut être défini par classe qui dérive de classe contenant la méthode abstraite Classe abstraite : est une classe qui possède au moins une méthode abstraite Elle doit être spécifiée par mot-clé abstract - On ne peut pas créer un objet dont le type est une classe abstraite (càd on ne peut pas appliquer new à une classe abstraite) - Une classe qui dérive d ’une classe abstraite est elle aussi abstraite si : - elle n ’implante pas toutes les méthodes abstraites de la classe abstraite mère, ou - elle ajoute des méthodes abstraites - Un constructeur d ’une classe abstraite est appelé uniquement par les classes qui dérivent de la classe abstraite (à l ’aide de super) GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 11 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Récapitulatif sur les types de méthodes Méthode finale : ne peut pas être redéfinie par aucune classe dérivée Méthode abstraite : son implantation : - n ’est pas définie - doit définie par toute classe dérivée non abstraite Méthode statique : ne nécessite pas création d ’un objet Autres méthodes GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 12 6 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Exemple de classe abstraite (Fig. 4.5 dans [1]) abstract class Shape { abstract public double area( ); public Shape( String shapeName ) { name = shapeName; } final public boolean lessThan( Shape rhs ) { return area( ) < rhs.area( ); } final public String toString( ) { return name + “ of area ” + area( ); } private String name; } L ’instruction suivante est incorrecte : u = new Shape(“ rectangle ” ); GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 13 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Classe qui dérive d ’une classe abstraite - Fournit éventuellement un nouveau constructeur - redéfinit éventuellement des méthodes de la classe abstraite qui ne sont (dans la classe abstraite mère) : - ni finales - ni abstraites - Implante éventuellement des méthodes abstraites de la classe (abstraite) mère - Définit éventuellement de nouvelles méthodes (qui peuvent être abstraites) GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 14 7 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Exemples de classes qui dérivent d ’une classe abstraite public class Circle extends Shape { public Circle( double rad ) { super( "circle" ); radius = rad; } (Fig. 4.6 dans [1]) public double area( ) { return PI * radius * radius; } private static final double PI = 3.14159265358979323; private double radius; } public class Rectangle extends Shape { public Rectangle( double len, double wid ) { super( "rectangle" ); length = len; width = wid; } public double area( ) { return length * width; } Les classes Circle et Rectangle dérivent de Shape La classe Square dérive de Rectangle private double length; private double width; } public class Square extends Rectangle { public Square( double side ) { super( side, side ); } } GEI 442 : Structures de données et algorithmes Hiver 2001 15 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique import java.io.*; Ahmed KHOUMSI Exemple d ’utilisation des classes de la page précédente (Fig. 4.7 dans [1]) class TestShape { private static BufferedReader in; private static void insertionSort( Shape [ ] a ) // Implantation page 83 } private static Shape readShape( ) // Implantation page 84 } { { ( Effectue le tri de plusieurs Shapes selon l ’ordre croissant de leurs surfaces) public static void main( String [ ] args ) { try { // Get number of shapes System.out.println( "Enter # of shapes: " ); in = new BufferedReader( new InputStreamReader( System.in ) ); int numShapes = Integer.parseInt( in.readLine() ); // Read the shapes Shape [ ] array = new Shape[ numShapes ]; for( int i = 0; i < numShapes; i++ ) array[ i ] = readShape( ); // Sort and output insertionSort( array ); System.out.println( "Sorted by area:" ); for( int i = 0; i < numShapes; i++ ) System.out.println( array[ i ] ); } catch( Exception e ) { System.out.println( e ); } } } GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 16 8 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Exemple (suite) (Fig. 4.9 dans [1]) private static void insertionSort( Shape [ ] a ) { for( int p = 1; p < a.length; p++ ) { int j = p; Shape tmp = a[ p ]; for( ; j > 0 && tmp.lessThan( a[ j - 1 ] ); j-- ) a[ j ] = a[ j - 1 ]; a[ j ] = tmp; } } GEI 442 : Structures de données et algorithmes Hiver 2001 17 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique private static double double double String Ahmed KHOUMSI Shape readShape( ) { rad; len; wid; oneLine; Exemple (suite) (Fig. 4.8 dans [1]) Try { System.out.println( "Enter shape type:" ); Do { oneLine = in.readLine( ); } while( oneLine.length( ) == 0 ); switch( oneLine.charAt( 0 ) ) { case 'c': System.out.println( "Enter radius: " ); rad = Double.valueOf( in.readLine( ) ).doubleValue( return new Circle( rad ); case 's': System.out.println( "Enter side: " ); len = Double.valueOf( in.readLine( ) ).doubleValue( return new Square( len ); case 'r': System.out.println( "Enter length and width " + "on separate lines: " ); len = Double.valueOf( in.readLine( ) ).doubleValue( wid = Double.valueOf( in.readLine( ) ).doubleValue( return new Rectangle( len, wid ); default: System.err.println( "Need c, r, or s" ); return new Circle( 0 ); } ); ); ); ); } catch( IOException e ) { System.err.println( e ); return new Circle( 0 ); } } GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 18 9 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Héritage multiple Dans un héritage multiple, une classe peut hériter de plusieurs classes Problème : Possibilité de conflit, par exemple dans le cas suivant : - Une classe A dérive de deux classes B et C, et - B et C contiennent deux méthodes qui ont la même signature C++ supporte l ’héritage multiple JAVA : - ne supporte pas l ’héritage multiple - fournit une alternative à l ’héritage multiple : l ’interface GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 19 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Interface Est une classe abstraite contenant uniquement : - des méthodes public abstract - des champs de données public static final Ne fournit aucune implantation Spécifiée à l ’aide du mot-clé interface GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 20 10 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Implantation d ’interface Une interface I peut être implantée par une classe C qui : - fournit les définitions des corps de toutes les méthodes (abstraites) de l ’interface - en utilisant le mot-clé implements La classe C se comporte comme si elle avait dérivé d ’une classe abstraite spécifiée par I GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 21 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Exemple d ’implantation d ’interface Interface public interface Drawable { public void setColor(Color c); public void SetPosition(double x, double y); public void draw(DrawWindow dw); } Classe : - implantant l ’interface Drawable - dérivant de la classe Rectangle (voir page 15) public class DrawableRectangle extends Rectangle implements Drawable { // New instance variables private Color c; private double x, y; // A constructor public DrawableRectangle(double w, double h) { super(w, h); } // Implementations of the Drawable methods public void setColor(Color c) { this.c = c; } public void SetPosition(double x, double y) { this.x = x; this.y = y; } public void draw(DrawWindow dw) { dw.drawRect(x, y, w, h, c); } } On peut aussi définir les classes DrawableCircle et DrawableSquare Il y a d ’autres exemples d ’interfaces et de leurs implantations dans [2] (exemples 3.6 et 3.7, page 113) GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 22 11 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Exemple d ’utilisation d ’interface ([2], exemple 3.18, page 78) Shape[ ] shapes = new Shape[ 3 ]; // Create un array to hold shapes Drawable[ ] drawables = new Drawable[ 3 ]; // and an array to hold drawables // Create some drawable shapes DrawableCircle dc = new DrawableCircle(1.2); DrawableSquare ds = new DrawableSquare(2.4); DrawableRectangle dr = new DrawableRectangle (2.1, 4.8); // The shapes can be assigned to both arrays shapes[0] = dc; drawables[0] = dc; shapes[1] = ds; drawables[1] = ds; shapes[2] = dr; drawables[2] = dr; // Compute total area and draw the shapes by invoking the Shape and // the Drawable abstract methods double total_area = 0; for (int i = 0; i < shapes.length; i++) { total_area += shapes[i].area( ); // Compute the area of the shapes drawables[i].setPosition(i*10.0, i*10.0); drawables[i].draw(draw_window); // Assume draw_window defined somewhere } Il y a un autre exemple d ’utilisation d ’interface dans [2] (exemple 3.18, page 78) GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 23 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique Interfaces multiples Une classe peut implanter plusieurs interfaces : - en spécifiant les interfaces qu ’elle implante - en définissant les implantations de toutes les méthodes de ces interfaces Exemple : On considère les deux interfaces suivantes (Fig. 4.12 et 4.14 dans [1]) package Supporting; public interface Comparable { int compares( Comparable rhs ); boolean lessThan( Comparable rhs ); } package Supporting; public interface Hashable { int hash( int tableSize ); } GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 24 12 Chapitre 1 : Langage JAVA Partie 4 : Héritage Université de Sherbrooke Département de génie électrique et de génie informatique package Supporting; Interfaces multiples (suite) public final class MyInteger implements Comparable, Hashable { public MyInteger( ) { this( 0 ); } public MyInteger( int x ) { value = x; } public int intValue( ) return value; } { public String toString( ) { Implantation des deux interfaces (Fig. 4.15 dans [1]) return Integer.toString( value ); } public int compares( Comparable rhs ) { return value < ((MyInteger)rhs).value ? -1 : value == ((MyInteger)rhs).value ? 0 : 1; } public boolean lessThan( Comparable rhs ) { return value < ((MyInteger)rhs).value; } public boolean equals( Object rhs ) { return rhs != null && value == ((MyInteger)rhs).value; } public int hash( int tableSize ) { if( value < 0 ) return -value % tableSize; else return value % tableSize; } private int value; } GEI 442 : Structures de données et algorithmes Hiver 2001 Ahmed KHOUMSI 25 13