La liaison tardive/retardée/dynamique

Rappels sur le typage statique

Ainsi que nous l'avons vu, la compilation d'une application réalise un contrôle de type statique qui prend en compte la possibilité de définir des sous-classes et par-là une hiérarchie de classes.
Ce mécansime se traduit au niveau du «bytecode» produit par le compilateur 


Principe général de fonctionnement

Le principe est donc simple : la signature de la méthode à invoquer étant fixée et le type de l'objet auquel elle est appliquée connu, une méthode de signature correcte est recherchée en partant de la classe de l'objet et en remontant jusqu'à la classe Object.
La première rencontrée, qui Eatisfait le profile, est alors invoquée.

Insistons sur le fait, que ce n'est pas le type de la référence qui importe mais le type réel de l'objet référencé.
De plus, ainsi qu'il a été dit, la méthode s'exécute du point de vue de la vue des variables dans le contexte de la classe où elle est définie.

Cela correspond au schéma suivant :



Par contre, toute invocation de méthode ultérieure est réalisée selon le principe de liaison tardive, et donc en se fondant sur le type réel de l'objet dans la recherche de la méthode satisfaisant le profil qui a été déterminé par typage statique lors de la compilation.


Cela signifie, pour poursuivre notre exemple que


l'invocation de la méthode methode2 donnera lieu à une recherche de cette méthode avec le profil (déterminé à la compilation) à partir de la classe CL4 (type de l'objet courant).


La liaison tardive illustrée

L'exemple suivant résume les différents aspects tant de la liaison statique que de l'accès aux variables d'instance :



   --> cat Liaison1.java
   class A {
      string a = "a dans A";
      String b = "b dans A";
      String c = "c dans A";
      void fonc1( ){
         System.out.println("fonc1 dans A");
         System.out.println("----------");
         fonc2( ); fonc3( );
         System.out.println("**********");
      }
      void fonc2( ){
         System.out.println("fonc2 dans A");
         System.out.println(a); System.out.println(b);
         System.out.println(c); System.out.println("----------");
      }
      void fonc3( ){
         System.out.println("fonc3 dans A");
         System.out.println("----------");
      }
   }       
   class B extends A{
      String a = "a dans B";
      String b = "b dans B";
      void fonc2( ){
         System.out.println("fonc2 dans B");
         System.out.println(a); System.out.println(b);
         System.out.println(c); System.out.println("----------");    
      }
      void fonc3( ){
         System.out.println("fonc3 dans B");
         System.out.println(a); System.out.println(b);
         System.out.println(c); System.out.println("----------");
         }
   }                    
   class C extends B{
      String a = "a dans C";
      String c = "c dans C";
      void fonc2( ){
         System.out.println("fonc2 dans C");
         System.out.println(a); System.out.println(b);
         System.out.println(c); System.out.println("----------");
      }
   }
   public class Liaison1 {
      public static void main(String[ ] arg){
         B b = new C( );
         b . fonc1 ( );
      }
   }   
   --> java Liaison1
   fonc1 dans A   // A.fonc1 car objet de type C et fonc1 non déf. dans C et B   
   ----------
   fonc2 dans C   // C.fonc2 car objet de type C et fonc2 non déf. dans C:   
   a dans C           // vision de a dans C
   b dans B           // vision de b dans B car non masqué dans C
   c dans C           // vision de c dans C
   ----------
   fonc3 dans B   // B:fonc3 car objet de type C et fonc2 non déf. dans C:
   a dans B           // la vision de a dans B
   b dans B           // la vision de b dans B
   c dans A           // la vision de c dans A (car non masqué dans B)
   ----------
   **********     // retour de l'appel initial A.fonc1

Dernière mise à jour : 20 juin 2005

Valid XHTML 1.0! Valid CSS!