Notes sur le polymorphisme



Le polymorphisme n'est pas une notion propre a JAVA. JAVA n'est qu'un langage de programmation parmis d'autres qui implemente la notion de polymorphisme.


Le polymorphisme en deux mots

Considerons trois classes A, B et C telles que: C derive de B et B derive de A. Ce que l'on peut representer par la figure ci dessous:



En deux mots: "une instante de C est reconnue comme etant aussi une instance de B et de A". Par contre une instance de B est reconnue comme etant une instance de A mais pas de C.


Illustration

Considerons le programme suivant:

Fichier test.java
public class test
{
  public static void main (String[] atgv)
  {
    System.out.println("--- Creation d'une instance de la classe <> ---");
    b ib = new b();
    System.out.println("--- Creation d'une instance de la classe <> ---");
    c ic = new c();
    System.out.println(" ");

    System.out.println("ic instance de c ?: ");
      System.out.println(ic instanceof c);
    System.out.println("ic instance de b ?: ");
      System.out.println(ic instanceof b);
    System.out.println("ic instance de a ?: ");
      System.out.println(ic instanceof a);
    System.out.println(" ");

    System.out.println("ib instance de c ?: ");
      System.out.println(ib instanceof c);
    System.out.println("ib instance de b ?: ");
      System.out.println(ib instanceof b);
    System.out.println("ib instance de a ?: ");
      System.out.println(ib instanceof a);
  }
}

class a
{
  a()
  {
    System.out.println("Creation d'une instance de la classe <>.");
  }
}

class b extends a
{
  b()
  {
    System.out.println("Creation d'une instance de la classe <>.");
  }
}

class c extends b
{
  c()
  {
    System.out.println("Creation d'une instance de la classe <>.");
  }
}

A l'execution, on obtient:

C:\programmes\java>java test
--- Creation d'une instance de la classe <> ---
Creation d'une instance de la classe <>.
Creation d'une instance de la classe <>.
--- Creation d'une instance de la classe <> ---
Creation d'une instance de la classe <
>.
Creation d'une instance de la classe <>.
Creation d'une instance de la classe <>.

ic instance de c ?:
true
ic instance de b ?:
true
ic instance de a ?:
true

ib instance de c ?:
false
ib instance de b ?:
true
ib instance de a ?:
true

Utilisation

Considerons le programme suivant:

Fichier test.java
public class test
{
  public static void main (String[] atgv)
  {
    System.out.println("-- Creation d'une voiture --");
    voiture v = new voiture(11);
    System.out.println("-- Creation d'une moto --");
    moto m = new moto(22);
    System.out.println("-- Numero de la voiure :"+ v.Get_Numero());
    System.out.println("-- Numero de la moto :"+ m.Get_Numero());
  }
}

class vehicule
{
  int numero;

  vehicule()
  {
    System.out.println("Creation d'un vehicule");
  }
  
  int Get_Numero() { return numero; }
}

class moto extends vehicule
{
  moto(int n)
  {
    System.out.println("Creation d'une mote - numero: " + n);
    numero = n;
  }
}

class voiture extends vehicule
{
  voiture(int n)
  {
    System.out.println("Creation d'une voiture - numero: " + n);
    numero = n;
  }
}

A l'execution on obtient le resultat suivant:

C:\programmes\java>java test
-- Creation d'une voiture --
Creation d'un vehicule
Creation d'une voiture - numero: 11
-- Creation d'une moto --
Creation d'un vehicule
Creation d'une mote - numero: 22
-- Numero de la voiure :11
-- Numero de la moto :22


Remarquer que la fonction Get_Numero() n'est pas definie dans les classes voiture et moto. Get_Numero est definie dans la classe vehicule.

Dans ces conditions comment se fait il que le compilateur accepte d'appliquer la methode Get_Numero() a des instances des classes voiture et moto ?

Les classes voiture et moto derivent de la classe vehicule. Par consequent les handles v (sur voiture) et m (sur moto) contiennent les informations suivantes:
  • v pointe sur une instance de vehicule, et "plus particuliairement" c'est une voiture.
  • m pointe sur une instance de vehicule, et "plus particuliairement" c'est une moto.


Lors de l'appel a v.Get_Numero(), v est reconnu en tant que vehicule.

Remarque: Nous aurions pu definir la méhode Get_Numero() dans les classes voiture et moto. Cela reviendrait a surcharger la methode Get_Numero(). A l'execution le resultat aurait ete le meme. Toutefois cela nous oblige a maintenir deux versions de la fonction Get_Numero().

Le sur casting

Reprenons l'exemple precedent, legerement modifie:

public class test
{
  public static void main (String[] atgv)
  {
    System.out.println("-- Creation d'une voiture --");
    voiture v = new voiture(11);
    System.out.println("-- Creation d'une moto --");
    moto m = new moto(22);
    System.out.println("-- Creation d'un vehicule --");
    vehicule vv = new vehicule();

    System.out.println("-- Numero du vehicule :"+ Get_Numero(vv));
    System.out.println("-- Numero de la voiure :"+ Get_Numero(v));
    System.out.println("-- Numero de la moto :"+ Get_Numero(m));

  }

  static int Get_Numero(vehicule vh) { return vh.numero; }

}

class vehicule
{
  int numero;

  vehicule()
  {
    System.out.println("Creation d'un vehicule");
  }
}

class moto extends vehicule
{
  moto(int n)
  {
    System.out.println("Creation d'une mote - numero: " + n);
    numero = n;
  }
}

class voiture extends vehicule
{
  voiture(int n)
  {
    System.out.println("Creation d'une voiture - numero: " + n);
    numero = n;
  }
}


A l'execution, nous obtenons:

C:\programmes\java>java test
-- Creation d'une voiture --
Creation d'un vehicule
Creation d'une voiture - numero: 11
-- Creation d'une moto --
Creation d'un vehicule
Creation d'une mote - numero: 22
-- Creation d'un vehicule --
Creation d'un vehicule
-- Numero du vehicule :0
-- Numero de la voiure :11
-- Numero de la moto :22


Dans ce cas, lors de l'appel de la methode Get_Numero, les instances de voiture et de moto sont "sur caster" est vehicule.

Attention !

static int Get_Numero(vehicule vh) { return vh.numero; }

La variable vh est de type vehicule et non voiture ou moto. Lors de l'appel Get_Numero(v), seule "la partie vehicule" de v est transmise a la variable vh. On peut dire qu'il y a "perte d'information".


L'exemple qui suit provoque une erreur de compillation:

Fichier test.java
public class test
{
  public static void main (String[] atgv)
  {
    System.out.println("-- Creation d'une voiture --");
    voiture v = new voiture(11);
    System.out.println("-- Creation d'une moto --");
    moto m = new moto(22);
    System.out.println("-- Creation d'un vehicule --");
    vehicule vv = new vehicule();

    System.out.println("-- Numero de la voiure :"+ Get_Numero(v));
    System.out.println("-- Numero de la moto :"+ Get_Numero(m));
  }

  static int Get_Numero(vehicule vh)
  {
     vh.type(); // provoque une erreur de compilation !
     return vh.numero;
  }

}

class vehicule
{
  int numero;

  vehicule()
  {
    System.out.println("Creation d'un vehicule");
  }
}

class moto extends vehicule
{
  moto(int n)
  {
    System.out.println("Creation d'une mote - numero: " + n);
    numero = n;
  }

  void type() { System.out.println(" => Moto"); }
}

class voiture extends vehicule
{
  voiture(int n)
  {
    System.out.println("Creation d'une voiture - numero: " + n);
    numero = n;
  }

  void type() { System.out.println(" => Voiture"); }
}


La compilation de ce programme genere l'erreur quivante:

C:\programmes\java>javac test.java
test.java:18: Method type() not found in class vehicule.
     vh.type(); // provoque une erreur de compilation !
            ^
1 error