Aujourd'hui, je me pose le problème de l'héritage d'un singleton. Un singleton est une classe tout ce qu'il y'a de plus classique, sauf que l'on s'interdit par pur sadisme de l'instancier plus d'une fois.

Celà donne en Java :

Singleton.java


public class Singleton {
       private static Singleton instance;

       private Singleton() {

       }

       public static Singleton getInstance() {
       	      if(instance == null) 
	      		  instance = new Singleton();
	      return instance;
       }
}

Wah, comme c'est révolutionnaire.
Ce qui est rudement sympathique par contre est la possibilité d'accéder à cette instance de n'importe ou (une sorte de variable globale en mieux forcément).

L'héritage de ce type de classe n'est pas sans poser quelques problèmes.
D'une part, le constructeur est privé, ce qui interdit d'emblée l'héritage. Toute solution ayant son problème, c'est tout naturellement que le mot clé protected existe. Celui ci permet l'accès des membres d'une classe aux classes filles uniquement.
D'autre part, le comportement singleton est implémenté dans des méthodes de classes, statiques et il n'est pas possible d'en hériter.

Boulet.java

public class Boulet extended Singleton {
       private static Boulet instance;

       protected Boulet() {
       	      super();
       }

       public static Boulet getInstance() {
       	      if(instance == null) 
	      		  instance = new Boulet();
	      return instance;
       }             
}

Vous remarquerez donc qu'il est nécessaire de réimplémenter le pattern singleton. Ce n'est pas la mort du petit cheval.
Le petit paradoxe dans l'histoire est que de fait, ma classe Boulet est aussi une classe Singleton. Donc, potentiellement, il peut exister plusieurs instances de la classe Singleton. A défaut de la mort du petit cheval, c'est la mort du design pattern.

Il est possible de faire de même en c++. Mais on peut faire vachement plus mieux encore.
En c++ existe la fantastique notion de template.
Le template est une sorte de préprocesseur ultime surpuissant qui permet en gros de paramétrer une classe par un type quelconque (C'est un peu pas terrible comme explication je sais).

Voici donc mon petit moule de classe singleton :

Singleton.hpp

using namespace std;
#include <stdlib.h>

template <typename T>
class Singleton {
 public: 
  static T * getInstance();

 private:
  Singleton();

 private:
  static T * instance;
};

template <typename T>
T * Singleton<T>::instance = NULL;

template <typename T>
Singleton<T>::Singleton() {

}

template <typename T>
Singleton<T>::~Singleton() {

}

template <typename T>
T * Singleton<T> :: getInstance() {
  if (instance == NULL) {
    instance = new T();
  }
  return instance;
}

Et voici une classe fille d'une des classes générées par ce template :

Boulet.hpp

#include "Singleton.hpp"

class Boulet : public Singleton<Boulet> {
      friend class Singleton<Boulet>;
}

Boulet hérite de la classe template Singleton paramétrée par elle même (encore une variante de l'oeuf ou la poule !).
C'est extrêmement classe et lisible (!?).
Le clou du spectacle est l'utilisation du mot clé friend. Autrement dit, je viens de piétiner le principe même d'encapsulation.
Si c'est pas la classe ça.
Comme quoi, on peut également faire des choses assez moches en c++.

Voilà, je n'ai pas voulu aller plus loin. C'est tout à fait possible de le faire, mais je ne suis pas qualifié pour.

ps : Les classes données en exemple ne font rien mais non seulement, elles illustrent bien la vie solitaire du singleton, mais en plus il est tout à fait possible de les étoffer avec de la volonté.