P
'
t
i
t
e
C
h
a
t
t
e
 
spacer~ ALCOHOL & CALCULUS DON'T MIX. NEVER DRINK & DERIVE Articles | Connexion
 
~GRAIN DE SEL

 Java, Constructeurs et Methodes Exportees
29/03/2006 - 10:11

L'invocation depuis un constructeur de methodes exportees est une faute tres commune en Java, et plus generalement en POO. Je le sais tres bien puisque je commets cette faute, consciemment toutefois, tres regulierement. Avant de continuer, rappelons qu'une methode exportee est une methode publique, protegee ou package-private appartenant a une classe non final, c'est-a-dire une methode qu'une classe fille peut redefinir.

A premiere vue, invoquer une methode exportee depuis le constructeur semble parfaitement valide et meme signe d'une bonne conception puisqu'on ne duplique pas d'instructions :

public class BreakMe {
    protected String name;
    protected String cached;

    public BreakMe(String name) {
        setName(name);
    }
    
    public void setName(String name) {
        this.name = name;
        this.cached = name.toUpperCase();
    }
    
    public String getName() {
        return cached;
    }
}

Le code de cette classe tres simple conserve en memoire le nom passe en parametre ainsi qu'une copie en majuscules. La methode getName renvoie toujours la copie en majuscules pour forcer les clients de cette API a respecter la casse choisie. L'appel a setName dans le constructeur semble etre une bonne solution, surtout si d'autres constructeurs sont ajoutes par la suite. Le code de la methode n'aura pas a etre duplique dans chaque constructeur.

Cette classe est malheureusement dangereuse car elle peut mener a l'obtention d'objets a moitie initialise. Comment cela est-ce possible ? Je vous presente la diabolique classe fille :

public class Breaker extends BreakMe {
    public Breaker(String name) {
        super(name);
    }
    
    public void setName(String name) {
        this.name = "Utah Boy";
    }
    
    public static void main(String... args) {
        Breaker b = new Breaker("Gredin");
        System.out.printf("la longueur du nom est de %s caracteres.",
          b.getName().length());
    }
}

Cette nouvelle classe etend la premiere pour imposer le nom, malgre le parametre. Le brouillon qui a redige cette classe n'a malheureusement pas lu le code source de la premiere, ou a ete induit en erreur par une mauvaise documentation, et ne realise que l'operation la plus evidente, l'assignement du champ name. Apres execution du constructeur, le champ cached n'a toujours pas ete initialise et le programme ci-dessus plante miserablement :

gfx@undead /cygdrive/d
$ java Breaker
Exception in thread "main" java.lang.NullPointerException
        at Breaker.main(Breaker.java:12)

Cet exemple est bien sur artificiel et peut etre corrige dans la classe fille en invoquant super.setName("Utah Boy") mais il s'agit d'un cas tres simple. De nombreux bugs, parfois subtils, peuvent etre provoques par une conception similaire. La seule solution valable est donc d'interdire dans les constructeurs les appels a des methodes exportees. Rien ne vous empeche cependant de factoriser votre code : utilisez this(...) pour faire converger les constructeurs vers un seul et unique ou utilisez des methodes d'initialisations privees.



Cette news a été rédigée en écoutant Offspring - Rage Againt Myself


 Romain GUY (Gfx)

 mercredi 29 mars 2006 @ 10:57
  
Continue sur ta lancée avec ce genre de post, j'adore!
C'est ludique et on y apprend des petites choses bien sympathiques :)
Tulipe.moutarde 
Gravatar Image
 mercredi 29 mars 2006 @ 11:02
  
Tu peux aussi fouiller les anciens posts si tu les as rates. Cherche notamment GC, Generics et private.

Cette réponse a été rédigée en écoutant Sahara Hotnights - Stay-Stay Away
Gfx 
Gravatar Image
 mercredi 29 mars 2006 @ 12:00
  
En fait, faudrait que tu mettes des catégories sur tes posts :) Geekeries, fonfonnages, etc.
Wizmaster 
Gravatar Image
 mercredi 29 mars 2006 @ 12:01
  
Non, flemme :)

Cette réponse a été rédigée en écoutant Smash Mouth - I'm A Believer
Gfx 
Gravatar Image
 mercredi 29 mars 2006 @ 12:30
  
Tain , c'est chiant, faut lire :runrunrun:
Ryle 
Gravatar Image

 Ajoutez votre grain de sel 
 
Surnom :
E-mail :
Message :     B     I     U     CODE     QUOTE     IMAGE     CD CASE     LINK 
 
Un gâteau ?oui    non 
RisoliVillard ?oui    non 
Port de RisoliVillard :
     


 Aide
RisoliVillard est un plugin Winamp 2/5, iTunes et un outil pour XMMS qui vous permettra d'afficher la chanson que vous écoutez au moment de l'écriture de votre réponse. Le port utilisé par votre plugin doit être reproduit dans le champ ci-dessus (8462 par défaut).
Utilisation de vBCode :
- [B]gras[/B]
- [I]italique[/I]
- [U]souligné[/U]
- [QUOTE]citation[/QUOTE]
- [CODE]code[/CODE]
- [IMG]http://www.serveur.com/image.jpg[/IMG]
- [URL=http://www.serveur.com/]texte à afficher[/URL]

 
#ProgX©2005 Mathieu GINOD - Romain GUY - Erik LOUISE