Héritage d'un singleton...
Par ryune le mercredi, juin 11 2008, 15:46 - Bural, Bureaux - Lien permanent
Dans la vie, on se pose parfois des questions à la con.
Dans la vie d'informaticien, on se pose des question d'informaticien
encore plus à la con.
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é.
Commentaires
Coucou, je voulais connaître la licence du code, GPL ?
Bon je plaisante.
Tout ça pour dire que ça me rappelle bien quelque chose ce que tu racontes là.
et après, on ose dire que la POO en perl, c'est de la bidouille... :D
...et en plus de piétiner l'encapsulation, on sombre dans le fameux cas du singleton pas thread-safe sur lequel tant de développeurs Java ont trouvé à redire. C'est du propre :o
Ma solution : dans ton premier script, tu remplaces "public class Singleton" par "public final class Singleton"
Plus de problème d'héritage !
J'ai honteusement oublier de remercier error3 qui avait déjà subit mes états d'âme à ce sujet.
Je le remercie donc pour la longue correspondance préalable que nous avons eu sur ce sujet ainsi que pour ses remarques et critiques.
Plus sérieusement (que dans mon dernier com) le mieux est de ne pas hériter d'un singleton, mais on peut toujours émuler l'héritage en faisant de l'extension, en mettant une instance de la classe "mère" comme membre de la classe "fille". Ça oblige à déclarer explicitement toutes les méthodes même si c'est pour transmettre à la classe "mère" sans rien faire de plus, mais c'est mieux que rien.
Euh... les templates tu les as aussi en Java, maintenant? Ou comment faire une soupe abominable en Java aussi.