Java : Heritages, Bonnes pratiques

Java est un langage puissant qui est parfois sous utilisé. Il est parfois nécessaire d’écrire des lignes de code très longue pour faire des cast dans tout les sens. Mais cela n’est parfois pas obligatoire.

L’héritage a du bon. Il faut l’utiliser pleinement !

Partons d’un exemple concret pour illustrer le propos d’aujourd’hui :

  1. interface IFoo {
  2. }
  3. class AFoo implements IFoo {
  4. }
  5. class A {
  6.  protected IFoo foo;
  7.  
  8.  public A() {
  9.   this.foo = new AFoo();
  10.  }
  11.  
  12.  protected IFoo getFoo() {
  13.   return foo;
  14.  }
  15.  
  16.  protected void something() {
  17.   getFoo().doStuff();
  18.  }
  19. }

Imaginons maintenant que nous ayons a faire de l’héritage :

  1. class BFoo implements IFoo {
  2. }
  3.  
  4. class B extends A {
  5.  
  6.  public B() {
  7.   this.foo = new BFoo();
  8.  }
  9.  
  10.  public void useFoo() {
  11.   getFoo().doStuff();
  12.  
  13.   ((BFoo)getFoo()).doSpecificBFooStuff();
  14.  }
  15. }

Bon, pour résumer avant de vous perdre, on a une classe A qui dispose d’une propriété de type IFoo. On a une classe B qui étend cette classe A. Dans sa logique, la classe B connait le type concret de la variable foo et a besoin d’accéder à certaines méthodes de la classe concrète de BFoo.

Si on en reste là, dans la classe B, on doit à chaque fois faire un cast à l’appel de getFoo() pour accéder aux méthodes spécifiques de BFoo.

Et bien, la magie de Java vous autorise à faire ça :

Dans la classe B vous avez tout à fait le droit d’écrire :

  1.     @Override
  2.     protected BFoo getFoo() {
  3.         return (BFoo)super.getFoo();
  4.     }

Je vous vois sceptique ! Oui oui le @Override à tout son sens, nous overridions bien la méthode getFoo() de la classe A.
L’intérêt est ici de faire le cast une seule fois dans le getter et ensuite de l’utiliser ailleurs sans avoir à faire des casts.

On peut donc réécrire la méthode useFoo() comme suit :

  1.  public void useFoo() {
  2.   getFoo().doStuff();
  3.  
  4.   getFoo().doSpecificStuff();
  5.  }

Quoi ? Comment est-ce possible ?
En soit, vous ne modifiez pas la signature de la méthode puisque vous retournez une Classe (mais cela fonctionne aussi avec une interface) qui étend l’interface générique. Donc vous overridez toujours la méthode !

Bénéfice : plus de cast à faire dans la classe qui utilise la méthode.

Le commentaires sont fermés.