Cette question n'est pas pour la discussion de savoir si le modèle de conception singleton est souhaitable ou non , ou pour toute guerre religieuse, mais pour discuter de la meilleure façon de mettre en œuvre ce modèle en Python de la manière la plus pythonique. Dans ce cas, je définis «le plus pythonique» pour signifier qu'il suit le «principe du moindre étonnement» .
J'ai plusieurs classes qui deviendraient singletons (mon cas d'utilisation est pour un enregistreur, mais ce n'est pas important). Je ne souhaite pas encombrer plusieurs classes avec une gomme ajoutée quand je peux simplement hériter ou décorer.
Meilleures méthodes:
Méthode 1: Un décorateur
def singleton(class_):
instances = {}
def getinstance(*args, **kwargs):
if class_ not in instances:
instances[class_] = class_(*args, **kwargs)
return instances[class_]
return getinstance
@singleton
class MyClass(BaseClass):
pass
Avantages
- Les décorateurs sont additifs d'une manière qui est souvent plus intuitive que l'héritage multiple.
Les inconvénients
- Alors que les objets créés à l'aide de MyClass () seraient de vrais objets singleton, MyClass lui-même est une fonction, pas une classe, vous ne pouvez donc pas appeler de méthodes de classe à partir de celle-ci. Aussi pour
m = MyClass(); n = MyClass(); o = type(n)();
alorsm == n && m != o && n != o
Méthode 2: une classe de base
class Singleton(object):
_instance = None
def __new__(class_, *args, **kwargs):
if not isinstance(class_._instance, class_):
class_._instance = object.__new__(class_, *args, **kwargs)
return class_._instance
class MyClass(Singleton, BaseClass):
pass
Avantages
- C'est une vraie classe
Les inconvénients
- Héritage multiple - eugh!
__new__
pourrait être écrasé lors de l'héritage d'une deuxième classe de base? Il faut penser plus que nécessaire.
Méthode 3: une métaclasse
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
#Python2
class MyClass(BaseClass):
__metaclass__ = Singleton
#Python3
class MyClass(BaseClass, metaclass=Singleton):
pass
Avantages
- C'est une vraie classe
- Couvre automatiquement l'héritage
- Utilise
__metaclass__
pour son bon usage (et m'a fait prendre conscience de cela)
Les inconvénients
- Y a-t-il?
Méthode 4: le décorateur renvoie une classe du même nom
def singleton(class_):
class class_w(class_):
_instance = None
def __new__(class_, *args, **kwargs):
if class_w._instance is None:
class_w._instance = super(class_w,
class_).__new__(class_,
*args,
**kwargs)
class_w._instance._sealed = False
return class_w._instance
def __init__(self, *args, **kwargs):
if self._sealed:
return
super(class_w, self).__init__(*args, **kwargs)
self._sealed = True
class_w.__name__ = class_.__name__
return class_w
@singleton
class MyClass(BaseClass):
pass
Avantages
- C'est une vraie classe
- Couvre automatiquement l'héritage
Les inconvénients
- N'y a-t-il pas une surcharge pour créer chaque nouvelle classe? Ici, nous créons deux classes pour chaque classe que nous souhaitons faire un singleton. Bien que cela soit bien dans mon cas, je crains que cela ne soit pas à l'échelle. Bien sûr, il y a un débat pour savoir s'il serait trop facile de mettre à l'échelle ce modèle ...
- Quel est l'intérêt de l'
_sealed
attribut - Impossible d'appeler des méthodes du même nom sur les classes de base à l'aide
super()
car elles vont récurrentes. Cela signifie que vous ne pouvez pas personnaliser__new__
et ne pouvez pas sous-classer une classe qui a besoin de vous pour appeler__init__
.
Méthode 5: un module
un fichier module singleton.py
Avantages
- Simple, c'est mieux que complexe
Les inconvénients
foo.x
ou si vous insistez à laFoo.x
place deFoo().x
); utilisez les attributs de classe et les méthodes statiques / de classe (Foo.x
).Réponses:
Utiliser une métaclasse
Je recommanderais la méthode n ° 2 , mais il vaut mieux utiliser une métaclasse qu'une classe de base. Voici un exemple d'implémentation:
Ou en Python3
Si vous souhaitez exécuter
__init__
chaque fois que la classe est appelée, ajoutezà la
if
déclaration enSingleton.__call__
.Quelques mots sur les métaclasses. Une métaclasse est la classe d'une classe ; c'est-à-dire qu'une classe est une instance de sa métaclasse . Vous trouvez la métaclasse d'un objet en Python avec
type(obj)
. Les classes normales de nouveau style sont de typetype
.Logger
dans le code ci-dessus sera de typeclass 'your_module.Singleton'
, tout comme la (seule) instance deLogger
sera de typeclass 'your_module.Logger'
. Lorsque vous appelez avec enregistreurLogger()
, Python demande d' abord la métaclasseLogger
,Singleton
, ce qu'il faut faire, ce qui permet la création d'instance à préempté. Ce processus est le même que Python demandant à une classe quoi faire en appelant__getattr__
lorsque vous faites référence à l'un de ses attributs en faisantmyclass.attribute
.Une métaclasse décide essentiellement ce que signifie la définition d'une classe et comment mettre en œuvre cette définition. Voir par exemple http://code.activestate.com/recipes/498149/ , qui recrée essentiellement des styles C
struct
en Python à l'aide de métaclasses. Le fil Quels sont les cas d'utilisation (concrets) des métaclasses? fournit également quelques exemples, ils semblent généralement liés à la programmation déclarative, en particulier telle qu'elle est utilisée dans les ORM.Dans cette situation, si vous utilisez votre méthode n ° 2 et qu'une sous-classe définit une
__new__
méthode, elle sera exécutée à chaque appelSubClassOfSingleton()
, car elle est responsable de l'appel de la méthode qui renvoie l'instance stockée. Avec une métaclasse, elle ne sera appelée qu'une seule fois , lorsque la seule instance sera créée. Vous voulez personnaliser ce que cela signifie d'appeler la classe , qui est déterminée par son type.En général, il est logique d'utiliser une métaclasse pour implémenter un singleton. Un singleton est spécial car il n'est créé qu'une seule fois , et une métaclasse est la façon dont vous personnalisez la création d'une classe . L'utilisation d'une métaclasse vous donne plus de contrôle au cas où vous auriez besoin de personnaliser les définitions de classe singleton d'une autre manière.
Vos singletons n'auront pas besoin d'héritage multiple (car la métaclasse n'est pas une classe de base), mais pour les sous-classes de la classe créée qui utilisent l'héritage multiple, vous devez vous assurer que la classe singleton est la première / la plus à gauche avec une métaclasse qui redéfinit
__call__
Il est très peu probable que ce soit un problème. Le dict d'instance n'est pas dans l'espace de noms de l'instance, il ne le remplacera donc pas accidentellement.Vous entendrez également que le modèle singleton viole le «principe de responsabilité unique» - chaque classe ne doit faire qu'une seule chose . De cette façon, vous n'avez pas à vous soucier de gâcher une chose que le code fait si vous devez en changer une autre, car ils sont séparés et encapsulés. L'implémentation de la métaclasse réussit ce test . La métaclasse est responsable de l' application du modèle et la classe et les sous-classes créées n'ont pas besoin de savoir qu'elles sont des singletons . La méthode n ° 1 échoue à ce test, comme vous l'avez noté avec "MyClass lui-même est une fonction, pas une classe, vous ne pouvez donc pas appeler de méthodes de classe à partir de celle-ci."
Version compatible Python 2 et 3
Écrire quelque chose qui fonctionne à la fois en Python2 et 3 nécessite l'utilisation d'un schéma légèrement plus compliqué. Étant donné que les métaclasses sont généralement sous - classes de type
type
, il est possible d'utiliser un pour créer dynamiquement une classe de base intermédiaire au moment de l' exécution avec elle comme métaclasse et utiliser alors que les baseclass du publicSingleton
classe de base. Il est plus difficile à expliquer qu'à faire, comme illustré ci-dessous:Un aspect ironique de cette approche est qu'elle utilise le sous-classement pour implémenter une métaclasse. Un avantage possible est que, contrairement à une métaclasse pure,
isinstance(inst, Singleton)
il reviendraTrue
.Corrections
Sur un autre sujet, vous l'avez probablement déjà remarqué, mais l'implémentation de la classe de base dans votre message d'origine est incorrecte.
_instances
doit être référencé sur la classe , vous devez utilisersuper()
ou vous êtes récursif , et__new__
est en fait une méthode statique à laquelle vous devez passer la classe , pas une méthode de classe, car la classe réelle n'a pas encore été créée quand elle est appelé. Toutes ces choses seront également vraies pour une implémentation de métaclasse.Décorateur retournant une classe
Au départ, j'écrivais un commentaire mais c'était trop long, je vais donc l'ajouter ici. La méthode # 4 est meilleure que l'autre version de décorateur, mais c'est plus de code que nécessaire pour un singleton, et ce n'est pas aussi clair.
Les principaux problèmes proviennent de la classe étant sa propre classe de base. Tout d'abord, n'est-il pas étrange qu'une classe soit une sous-classe d'une classe presque identique avec le même nom qui n'existe que dans son
__class__
attribut? Cela signifie également que vous ne pouvez pas définir de méthodes qui appellent la méthode du même nom sur leur classe de base avec,super()
car elles recurseront. Cela signifie que votre classe ne peut pas être personnalisée__new__
et ne peut dériver d'aucune classe qui doit y faire__init__
appel.Quand utiliser le motif singleton
Votre cas d'utilisation est l' un des meilleurs exemples de vouloir utiliser un singleton. Vous dites dans l'un des commentaires "Pour moi, l'exploitation forestière a toujours semblé un candidat naturel pour les Singletons." Tu as absolument raison .
Lorsque les gens disent que les singletons sont mauvais, la raison la plus courante est qu'ils sont un état partagé implicite . Alors qu'avec les variables globales et les importations de module de niveau supérieur , l'état partagé est explicite , les autres objets qui sont transmis sont généralement instanciés. C'est un bon point, à deux exceptions près .
Le premier, et celui qui est mentionné à divers endroits, est lorsque les singletons sont constants . L'utilisation de constantes globales, en particulier les énumérations, est largement acceptée et considérée comme raisonnable car, quoi qu'il arrive , aucun des utilisateurs ne peut les gâcher pour un autre utilisateur . Cela est également vrai pour un singleton constant.
La deuxième exception, qui est moins mentionnée, est l'inverse - lorsque le singleton n'est qu'un récepteur de données , pas une source de données (directement ou indirectement). C'est pourquoi les bûcherons se sentent comme une utilisation "naturelle" des singletons. Comme les différents utilisateurs ne modifient pas les enregistreurs de la manière dont les autres utilisateurs se soucieront, il n'y a pas vraiment d'état partagé . Cela annule l'argument principal contre le modèle singleton et en fait un choix raisonnable en raison de leur facilité d'utilisation pour la tâche.
Voici une citation de http://googletesting.blogspot.com/2008/08/root-cause-of-singletons.html :
la source
__new__
dans une métaclasse, c'est quand la classe est nouvelle - quand elle est définie, pas quand l' instance serait nouvelle. L'appel de la classe (MyClass()
) est l'opération que vous souhaitez remplacer, pas la définition de la classe. Si vous voulez vraiment comprendre comment Python fonctionne, la meilleure chose que vous puissiez faire (à part continuer à l'utiliser) est de lire docs.python.org/reference/datamodel.html . Une bonne référence sur les métaclasses est eli.thegreenplace.net/2011/08/14/python-metaclasses-by-example . Un bon article sur les singletons est la série du blog Google que j'ai liée dans cette réponse.Les modules ne sont importés qu'une seule fois, tout le reste est sur-pensé. N'utilisez pas de singletons et essayez de ne pas utiliser de globaux.
la source
s = some_global_variable; str = pickle.dumps(s); s1 = pickle.loads(str); print s is s1; # False
is
opérateur teste l'égalité du pointeur. Je serais plutôt surpris --- au point de l'appeler un bug --- sipickle.loads
renvoyé une référence à un objet préexistant plutôt qu'une référence à un objet nouvellement créé. Ainsi, tester sis is s1
ne vous dit rien sur la pertinence d'utiliser des modules comme singletons.pickle.loads()
fait déjà, par exemple pour les instances debool
etNoneType
.pickle.loads(pickle.dumps(False)) is False
rendementsTrue
True
,False
etNone
, et n'a rien à voir avec le code derrièrepickle.loads
. En outre, il est sûr de le faire uniquement pour les objets en lecture seule. Si je devaispickle.loads
renvoyer une référence à un objet modifiable déjà existant, tel qu'un module, ce serait un bogue. (Et donc je maintiens mon implication que l'exemple de code de dividebyzero ne prouve rien.)Utilisez un module. Il n'est importé qu'une seule fois. Définissez-y des variables globales - ce seront les «attributs» de singleton. Ajoutez quelques fonctions - les «méthodes» du singleton.
la source
Vous n'avez probablement jamais besoin d'un singleton en Python. Définissez simplement toutes vos données et fonctions dans un module et vous avez un singleton de facto.
Si vous devez vraiment absolument avoir une classe singleton, alors j'irais avec:
Utiliser:
où mysingleton.py est votre nom de fichier dans lequel My_Singleton est défini. Cela fonctionne car après la première importation d'un fichier, Python ne réexécute pas le code.
la source
Voici une doublure pour vous:
Voici comment vous l'utilisez:
Votre objet est instancié avec impatience. Cela peut ou non être ce que vous voulez.
la source
type(wat)
ouwat.__class__
. Si vous voulez vraiment y parvenir, mieux définir la classe et l'instancier tout de suite, pas besoin de gâcher le décorateur.wat2 = type(wat)()
, mais c'est du python, nous sommes tous des adultes consentants et tout ça. Vous ne pouvez pas garantir qu'il n'y aura qu'une seule instance, mais vous pouvez garantir que si les gens en font une deuxième, cela aura l'air laid et - s'ils sont honnêtes et honnêtes - comme un signe d'avertissement pour eux. Qu'est-ce que je rate?Consultez la question Stack Overflow Existe-t-il un moyen simple et élégant de définir des singletons en Python? avec plusieurs solutions.
Je recommande fortement de regarder les exposés d'Alex Martelli sur les modèles de conception en python: partie 1 et partie 2 . En particulier, dans la partie 1, il parle de singletons / objets d'état partagés.
la source
Voici ma propre implémentation de singletons. Tout ce que vous avez à faire est de décorer la classe; pour obtenir le singleton, vous devez ensuite utiliser la
Instance
méthode. Voici un exemple:Et voici le code:
la source
SingletonList = Singleton(list).Instance(); print(SingletonList is type(SingletonList)())
devrait imprimerTrue
en vrai singleton; avec vos impressions de codeFalse
La méthode 3 semble être très soignée, mais si vous voulez que votre programme s'exécute à la fois en Python 2 et Python 3 , cela ne fonctionne pas. Même la protection des variantes séparées avec des tests pour la version Python échoue, car la version Python 3 donne une erreur de syntaxe dans Python 2.
Merci à Mike Watkins: http://mikewatkins.ca/2008/11/29/python-2-and-3-metaclasses/ . Si vous voulez que le programme fonctionne à la fois en Python 2 et Python 3, vous devez faire quelque chose comme:
Je suppose que «objet» dans l'affectation doit être remplacé par «BaseClass», mais je n'ai pas essayé cela (j'ai essayé le code comme illustré).
la source
class MyClass(metaclass=Singleton)
Eh bien, à part être d'accord avec la suggestion générale de Pythonic sur le fait d'avoir un niveau global au niveau du module, qu'en est-il:
La sortie est:
la source
_sealed
attribut? Pour autant que je vois cela ne fait rien? Quelque chose me dérange à ce sujet qui dit que cela ne devrait pas bien fonctionner ... Je ferai des tests comparatifs plus tard cette semaine.__init__
à appeler à chaque initialisation. Juste un simple 'Initialisation dans class.method'. quant à l'indentation - vous avez utilisé des tabulations et des espaces - j'en ai réparé la plupart, mais semblez en avoir manqué un si vous voulez l'obtenir (il suffit de consulter le journal d'édition)Que dis-tu de ça:
Utilisez-le comme décorateur dans une classe qui devrait être un singleton. Comme ça:
Ceci est similaire au
singleton = lambda c: c()
décorateur dans une autre réponse. Comme l'autre solution, la seule instance a le nom de la classe (MySingleton
). Cependant, avec cette solution, vous pouvez toujours "créer" des instances (en fait obtenir la seule instance) à partir de la classe, en faisantMySingleton()
. Il vous empêche également de créer des instances supplémentaires en faisanttype(MySingleton)()
(cela renvoie également la même instance).la source
type(MySingleton)()
,MySingleton.__init__()
est appelé et l'objet est initialisé plusieurs fois; vous pouvez le corriger en écrivantcls.__init__ = lambda self: pass
dans votresingleton
. En outre, le remplacementcls.__call__
semble inutile et même dangereux -__call__
défini dans ce contexte est utilisé lorsque vous appelezMySingleton(any, list, of, arguments)
, pas lorsque vous appeleztype(MySingleton)(any, list, of, arguments)
.__init__()
on appelle à nouveau en faisanttype(MySingleton)()
. La solution que vous avez proposée (en ajoutantcls.__init__ = lambda self: pass
) donne une erreur de syntaxe, car la dernière partie de l'expression lambda doit être une expression, pas une instruction. Cependant, en ajoutant descls.__init__ = lambda self: None
œuvres, j'ai donc ajouté cela à ma réponse.__call__
. mon intention était de faire les deuxtype(MySingleton)()
et deMySingleton()
renvoyer l'instance. Il fait donc ce que je voulais. Vous pouvez considérer MySingleton comme le type du singleton ou l'instance du singleton (ou les deux).Je vais jeter le mien dans le ring. C'est un simple décorateur.
Avantages, je pense que cela a sur certaines des autres solutions:
YourClass
. Cela inclut le fait de ne pas avoir besoin d'utiliser une métaclasse pour votre classe (notez que la métaclasse ci-dessus est en usine, pas la "vraie" classe).YourClass
, cela ressemble à une classe (car c'est le cas), et ils l'utilisent normalement. Pas besoin d'adapter les appelants à une fonction d'usine.YourClass()
instancie est toujours un véritable exemple de ce queYourClass
vous avez implémenté, pas un proxy d'aucune sorte, donc aucune chance d'effets secondaires en résultant.isinstance(instance, YourClass)
et des opérations similaires fonctionnent toujours comme prévu (bien que ce bit nécessite abc, il empêche donc Python <2.6).Un inconvénient me vient à l'esprit: les méthodes de classe et les méthodes statiques de la classe réelle ne peuvent pas être appelées de manière transparente via la classe d'usine qui la cache. Je l'ai utilisé assez rarement pour ne jamais rencontrer ce besoin, mais il serait facilement rectifié en utilisant une métaclasse personnalisée en usine qui implémente
__getattr__()
pour déléguer l'accès aux attributs tout-en-un à la classe réelle.Un modèle connexe que j'ai trouvé plus utile (pas que je dis que ce genre de choses sont nécessaires très souvent) est un modèle "Unique" où l'instanciation de la classe avec les mêmes arguments aboutit à récupérer la même instance. C'est-à-dire un "singleton par arguments". Ce qui précède s'adapte bien à cela et devient encore plus concis:
Cela dit, je suis d'accord avec l'avis général que si vous pensez avoir besoin de l'une de ces choses, vous devriez probablement vous arrêter un instant et vous demander si vous en avez vraiment besoin. 99% du temps, YAGNI.
la source
serial
communication, et pour créer une instance que vous souhaitez envoyer le port série comme argument, alors avec l'approche traditionnelle ne fonctionnera pasla source
Code basé sur la réponse de Tolli .
Explication:
Créer une nouvelle classe, héritant de given
cls
(elle ne change pas
cls
au cas où quelqu'un le voudrait par exemplesingleton(list)
)Créez une instance. Avant de
__new__
passer outre, c'est si facile.__new__
méthode définie il y a un instant.La fonction
instance
ne retourne que lorsque c'est ce que l'appelant attend, sinon il lèveTypeError
.La condition n'est pas remplie lorsque quelqu'un tente d'hériter d'une classe décorée.
instance
est déjà initialisé, donc la fonction remplace__init__
par la fonction qui ne fait rien.Voyez-le travailler en ligne
la source
Elle est légèrement similaire à la réponse de fab mais pas exactement la même.
Le contrat singleton n'exige pas que nous puissions appeler le constructeur plusieurs fois. Comme un singleton doit être créé une seule fois, ne devrait-il pas être vu comme créé une seule fois? «Usurper» le constructeur altère sans doute la lisibilité.
Donc, ma suggestion est juste ceci:
Cela n'exclut pas l'utilisation du constructeur ou du champ
instance
par code utilisateur:... si vous savez avec certitude que cela
Elvis
n'a pas encore été créé, et c'est le casKing
.Mais il encourage les utilisateurs à utiliser la
the
méthode de manière universelle:Pour faire cela, vous pouvez également remplacer
__delattr__()
pour lever une exception si une tentative de suppression est effectuéeinstance
, et remplacer__del__()
pour qu'il déclenche une exception (sauf si nous savons que le programme se termine ...)Améliorations supplémentaires
Mes remerciements à ceux qui ont contribué aux commentaires et aux modifications, dont d'autres sont les bienvenus. Bien que j'utilise Jython, cela devrait fonctionner plus généralement et être thread-safe.
Points à noter:
__new__
__new__
vous devez décorer avec @classmethod ou__new__
sera une méthode d'instance non liéethe
une propriété de niveau classe, éventuellement en la renommantinstance
la source
__new
__ plutôt que__init__
, car il agit uniquement sur les attributs de classe et cela empêche qu'il n'y ait brièvement une seconde instance. La différence entre cette méthode et la méthode 2 est de savoir si le fait d'initialiser plusieurs fois renvoie l'instance unique ou déclenche une exception. Je pense que je suis heureux que l'un ou l'autre satisfasse le modèle singleton, l'un est plus facile à utiliser, tandis que l'autre est plus explicite qu'il s'agit d'un singleton.__init__
empêche le sous- classement , mais bien que cela facilite les choses, ce n'est pas obligatoire__init__
afin que j'espère que cela devrait être sousthe
pourrait probablement bénéficier d'être une méthode de classe pour des raisons similairesUn paquebot (je ne suis pas fier, mais ça fait l'affaire):
la source
Si vous n'avez pas besoin d'une initialisation paresseuse de l'instance de Singleton, alors ce qui suit devrait être facile et thread-safe:
De cette façon,
A
un singleton est initialisé lors de l'importation du module.la source
Peut-être que j'ai mal compris le motif singleton mais ma solution est aussi simple et pragmatique (pythonique?). Ce code remplit deux objectifs
Foo
accessible partout (global).Foo
peut exister.Voici le code.
Production
la source
Après avoir lutté avec cela pendant un certain temps, j'ai finalement trouvé ce qui suit, de sorte que l'objet config ne soit chargé qu'une seule fois, lorsqu'il est appelé à partir de modules distincts. La métaclasse permet de stocker une instance de classe globale dans le dict intégré, qui semble actuellement être le moyen le plus pratique de stocker un programme global approprié.
la source
Je ne me souviens pas où j'ai trouvé cette solution, mais je la trouve la plus «élégante» de mon point de vue non expert en Python:
Pourquoi j'aime ça? Pas de décorateurs, pas de méta-classes, pas d'héritage multiple ... et si vous décidez que vous ne voulez plus que ce soit un Singleton, supprimez simplement la
__new__
méthode. Comme je suis nouveau sur Python (et OOP en général), je m'attends à ce que quelqu'un me dise pourquoi cette approche est terrible?la source
__new__
. Ne te répète pas .*args
et**kwargs
, et ensuite ne font rien avec elles? Les passer dansdict.__new__
la façon suivante :dict.__new__(cls, *args, **kwargs)
.__init__
méthode à chaque appel de la classe. Si votre__init__
méthode a réellement fait quelque chose, vous remarquerez le problème. Chaque fois que vous le faitesSomeSingleton()
, l'état de votre singleton est réinitialisé par la__init__
méthode.C'est ma façon préférée d'implémenter des singletons:
la source
Cette réponse n'est probablement pas celle que vous recherchez. Je voulais un singleton dans le sens où seul cet objet avait son identité, par rapport à. Dans mon cas, il était utilisé comme valeur sentinelle . Pour lequel la réponse est très simple, faites n'importe quel objet
mything = object()
et par nature de python, seule cette chose aura son identité.la source
eval
ouimportlib.reload
.Cette solution provoque une certaine pollution de l'espace de noms au niveau du module (trois définitions plutôt qu'une seule), mais je la trouve facile à suivre.
J'aimerais pouvoir écrire quelque chose comme ça (initialisation paresseuse), mais malheureusement les classes ne sont pas disponibles dans le corps de leurs propres définitions.
Comme cela n'est pas possible, nous pouvons décomposer l'initialisation et l'instance statique dans
Initialisation désirée:
Initialisation paresseuse:
Initialisation désirée:
la source