Quand on créer plusieurs instances de MySingleton héritant de MySuperSingleton, ça crash de partout. Je pense qu'il faut redéfinir toutes les méthodes dans MySingleton, et de toute manière il y aura un conflit pour la méthode allocWithZone: ...
Je ne suis pas sûr de bien comprendre ce que tu souhaites faire... ;D En fait la classe MySuperSingleton est déjà la base commune de laquelle je souhaite faire hériter les autres singleton (dans l'exemple).
A priori il n'est pas possible de ne pas redéfinir les méthodes shardeInstance, allocWithZone et init dans les sous-classes. Du coup la classe MySuperSingleton devient une sorte de classe "interface". J'ai fait un projet qui marche avec les classes MySingleton et MyOtherSingleton qui héritent de MySuperSingleton.
<br />static MySingleton *sharedInstance = nil;<br /><br />@implementation MySingleton<br /><br />- (id) init <br />{ <br /> @synchronized([self class]) <br /> {<br />Â Â Â Â Â Â if (!sharedInstance) <br /> Â {<br />Â Â Â Â Â Â Â Â Â if (self = [super init]) <br /> {<br />Â Â Â Â Â Â Â Â Â Â Â Â sharedInstance = self; <br />Â Â Â Â Â Â Â Â }<br />Â Â Â Â Â }<br />Â Â Â Â }<br /> <br />Â Â return sharedInstance;<br />}<br /><br /><br />+ (MySingleton *) sharedInstance <br />{<br /> @synchronized(self) <br /> {<br /> if(!sharedInstance) <br /> {<br /> [[self alloc] init];<br /> }<br /> }<br /> <br /> return sharedInstance; <br />}<br /><br /><br />+ (id) allocWithZone: (NSZone *)zone <br />{<br /> @synchronized(self) <br /> {<br /> if(!sharedInstance) <br /> {<br /> sharedInstance = [super allocWithZone: zone];<br /> return sharedInstance;<br /> }<br /> }<br /> <br /> return sharedInstance;<br />}<br /><br />@end<br />
ça marche en l'état mais ce qu'il serait bien c'est que les comportements implémentés dans allocWithZone:, init, et shardeInstance soient hérités de la super classe et pas redéfinis à chaque fois par chaque sous-classe... Est-ce possible à votre avis ?
Je ne suis pas sûr de bien comprendre ce que tu souhaites faire...
pareilÂ
Je vais tenter de clarifier les choses alors ! En fait, on peut trouver dans la doc Apple le code conseillé pour implémenter un singleton style NSUserDefaults ou encore NSFileManager.
Ce que je souhaite faire c'est UNE super classe de laquelle je peux en faire hériter plusieurs sans avoir à ré-implémenter le comportement d'un singleton (sans re-définir les méthode allocWithZone:, sharedInstance, init....).
Pour l'instant ça ne marche pas, je suis obliger de ré-écrire le code fournis par Apple dans chacune de mes sous-classes... Si tu veux c'est un peu comme si on pouvais avoir des CustomFileManager qui soient des singletons(sans redéfinitions) par la magie de l'héritage (sinon ça sert à rien d'utiliser l'héritage 8--))
Pourquoi tu ne fais pas comme moi un "File Template" dans Xcode te permettant de générer en 2 clics un singleton ?
Cf l'archive jointe, à dézipper et à mettre à côté des autres "File Templates" dans "/Developer/Library/Xcode/File Templates/Cocoa/" (pour les applis Mac) et dans "/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/File Templates/Cocoa Touch Class/" pour l'avoir aussi pour les projets iPhone
Tu quittes et relance Xcode (quoique je me demande si c'est nécessaire?) et quand tu es ensuite dans un de tes projets et veux créer un singleton, tu fais File -> New File et dans les templates proposés tu auras un nouveau template de fichier "Objective-C Singleton Class". Tu rentres le nom de ton fichier et Xcode fait tout le reste t'as plus rien à taper.
Si tu veux deux instances différentes, alors ce n'est plus un singleton.
C'est pas faux ??? comment faire alors pour partager le comportement de singleton à plusieurs classes différente ? :why?:
Pourquoi tu ne fais pas comme moi un "File Template" dans Xcode te permettant de générer en 2 clics un singleton ?
Oui c'est une bonne idée
cependant j'aimerais également que mes singletons partagent des variables et des méthodes qu'ils peuvent redéfinir...
Bon je sens que mes singletons vont devenir des classes normales comme ça il n'y aura plus de problèmes, l'implémentation de singleton ne doit pas se prêter à toutes ces histoires de partage de méthodes, variables et comportements...
En prenant mon exemple MultiSingleton, tu auras une instance et une seule par sous classe de Singleton, tu peux implémenter le code commun à ces 'singletons' dans BaseSingleton.
Sinon la méthode d'Aligator marche très bien, j'appelle ça le multi héritage du pauvre ???
Pour moi si tu veux : - une classe abstraite (non instanciable) ParentSingleton mutualisant des variables d'instance - une ou plusieurs classes concrètes, qui seront des singletons, dérivant de ParentSingleton pour récupérer les variables d'instance communes
Il suffit de : - ne pas implémenter sharedInstance dans ParentSingleton (et d'interdir le init si la class de self est ParentSingleton pour interdire son instanciation directe) - réimplémenter juste sharedInstance dans chacune des sous-classes de ParentSingleton : chacune initialisant/renvoyant la variable gloable déclarée en "static", celle qui mémorise l'instance singleton dès qu'elle est créée... puisque justement tu vas en avoir besoin d'une différente pour chacune de tes sous-classes si tu veux que chaque sous-classe soit singleton (et donc n'avoir qu'une instance de SingletonEnfant1, et une seule instance de SingletonEnfant2, mais que ces deux SingletonEnfantN ne partagent pas pour autant la même instance singleton...
Pour aller jusqu'au bout des idées, disont, 'tortueuses' de flo, la classe de base BaseSingleton est instanciée dans IB
On a donc MutiSingleton qui gère 3 Singletons et BaseSingleton qui contient 3 Outlets statiques, ce qui permet aux 3 singletons d'accéder aux 3 textFields.
Résultat: on a une instance orpheline de BaseSingleton, celle instanciée au chargement du nib, mais ça tombe bien car on en a besoin pour initialiser les outlets statiques
J'up cette discussion (suite à un message de 6ix qui mettais qu'il se penchait sur la question) pour vous fournir le template que j'avais fait à l'époque pour pouvoir facilement créer une nouvelle classe Singleton dans Xcode (en un clic), grâce aux "File Templates"
En effet, Apple nous fournit dans Xcode des modèles de classes (NSView subclass, UIViewController subclass, ...) mais rien ne nous empêche de rajouter nos propres modèles.
J'ai donc pris l'exemple d'Apple et en ai fait un copier/coller en remplaçant juste le nom en dur (Gizmo) par "FILEBASENAMEASIDENTIFIER" (j'ai pris modèle sur les pbfiletemplates existants). J'ai encapsulé ça dans un pbfiletemplate et voilà
Le principe d'installation est simple :
Téléchargez le fichier joint et décompressez l'archive
Copiez ce dossier "Objective-C Singleton.pbfiletemplate" dans vos dossiers de Templates pour Mac et pour iPhone (histoire que le template soit dispo pour les 2), à savoir :
Pour MacOSX : [tt]/Developer/Library/Xcode/File Templates/Cocoa Class[/tt]
Pour iPhone : [tt]/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/File Templates/Cocoa Touch Class[/tt]
NB : Il est aussi possible de créer un lien symbolique (par exemple dans le répertoire des templates de l'iPhone, faire un lien pointant sur le pbfiletemplate du répertoire de OSX) pour éviter la duplication
Apparemment, il n'est même pas nécessaire de relancer Xcode : vous pouvez dès à présent choisir dans Xcode le menu "File > New File..." puis choisir ce nouveau template pour ajouter un singleton au projet ouvert. Donnez un nom à votre fichier, il en déduira le nom de la classe singleton à créer et fera tout tout seul
Téléchargez le fichier joint et décompressez l'archive
Est-ce qu'il s'agit du fichier de ton post précédent... ?
Concernant les singleton, je dévie un peu de la discussion abordée jusqu'ici vers un aspect plus général. En lisant différentes discussions ici ou là , deux éléments reviennent souvent: (1) l'utilité réelle d'un Singleton (2) la façon d'implémenter un Singleton
(1) Le but d'un singleton est de définir une classe dont une seule instance uniquement peut être créée. Un autre avantage est de pouvoir y accéder facilement de n'importe où dans l'application, mais ce ne devrait pas être un argument en faveur de la création d'un singleton. L'argument est le suivant: si tout ce que l'on veut est avoir un accès partagé et facile à une instance, il suffit de créer une méthode +[UneClasse sharedClasse] ou +[UneClasse defaultClasse] (exemple: +[NSFileManager defaultManager]).
(2) Une façon d'implémenter un singleton est donnée par Apple dans sa doc. Mais elle ne fait pas forcément l'unanimité... Une implémentation donnée par Peter Hosey est celle donnée ci-dessous, qu'il juge plus correcte que celle d'Apple.
<br />@interface PRHEmptySingleton: NSObject<br />{<br />}<br /><br />+ (id) sharedFramistan;<br /><br />@end<br />static PRHEmptySingleton *sharedInstance = nil;<br /><br />@implementation PRHEmptySingleton<br /><br />+ (void) initialize {<br /> if (!sharedInstance) {<br /> //init will assign sharedInstance for us.<br /> [[self alloc] init];<br /> }<br />}<br /><br />+ (id) sharedFramistan {<br /> //Already set by +initialize.<br /> return sharedInstance;<br />}<br /><br />+ (id) allocWithZone:(NSZone *)zone {<br /> //Usually already set by +initialize.<br /> if (sharedInstance) {<br /> //The caller expects to receive a new object, so implicitly retain it to balance out the caller's eventual release message.<br /> return [sharedInstance retain];<br /> } else {<br /> //When not already set, +initialize is our caller"it's creating the shared instance. Let this go through.<br /> return [super allocWithZone:zone];<br /> }<br />}<br /><br />- (id) init {<br /> //If sharedInstance is nil, +initialize is our caller, so initialize the instance.<br /> //Conversely, if it is not nil, release this instance (if it isn't the shared instance) and return the shared instance.<br /> if (!sharedInstance) {<br /> if ((self = [super init])) {<br /> //Initialize the instance here.<br /> }<br /><br /> //Assign sharedInstance here so that we don't end up with multiple instances if a caller calls +alloc/-init without going through +sharedInstance.<br /> //This isn't foolproof, however (especially if you involve threads). The only correct way to get an instance of a singleton is through the +sharedInstance method.<br /> sharedInstance = self;<br /> } else if (self != sharedInstance) {<br /> [self release];<br /> self = sharedInstance;<br /> }<br /><br /> return self;<br />}<br /><br />@end<br />
Je serais donc intéressé à en débattre sur un forum francophone. 8--)
Heu juste pour dire que (1) en effet j'avais oublié de joindre le fichier à mon post ^^ c'est donc rattrapé, et (2) ah oui tiens bah en fait je l'avais déjà posté et justement dans ce post juste qques posts plus haut... j'avais même pas vu :P Comme quoi ^^
Pour ton alternative de code, j'ai pas le temps ce soi... heu matin (serait p'tet temps que j'aille me coucher non ?) mais je regarderai plus tard.
Une implémentation donnée par Peter Hosey est celle donnée ci-dessous, qu'il juge plus correcte que celle d'Apple.
Je connaissais, et je trouve son implémentation particulièrement élégante, car elle permet de se passer totalement de synchronisation, +initialize étant appelé par le runtime Objective-C de façon totalement "thread safe".
Réponses
On va faire au plus simple:
Si tu veux que tes singletons aient une base commune, tu fais hériter le super singleton de cette classe:
Je ne suis pas sûr de bien comprendre ce que tu souhaites faire... ;D
En fait la classe MySuperSingleton est déjà la base commune de laquelle je souhaite faire hériter les autres singleton (dans l'exemple).
A priori il n'est pas possible de ne pas redéfinir les méthodes shardeInstance, allocWithZone et init dans les sous-classes. Du coup la classe MySuperSingleton devient une sorte de classe "interface". J'ai fait un projet qui marche avec les classes MySingleton et MyOtherSingleton qui héritent de MySuperSingleton.
Est-ce correcte selon vous ?
MySuperSingleton : la classe parente
MySingleton une classe héritière :
ça marche en l'état mais ce qu'il serait bien c'est que les comportements implémentés dans allocWithZone:, init, et shardeInstance soient hérités de la super classe et pas redéfinis à chaque fois par chaque sous-classe... Est-ce possible à votre avis ?
Ha bon ?
Pourtant il n'existe bien qu'une seule instance pour chaque classe (Sauf la classe MySuperSingleton qui n'est pas voué à être instancié).
Tu pourrais être plus explicite ?
pareil
Je vais tenter de clarifier les choses alors !Â
En fait, on peut trouver dans la doc Apple le code conseillé pour implémenter un singleton style NSUserDefaults ou encore NSFileManager.
Ce que je souhaite faire c'est UNE super classe de laquelle je peux en faire hériter plusieurs sans avoir à ré-implémenter le comportement d'un singleton (sans re-définir les méthode allocWithZone:, sharedInstance, init....).
Pour l'instant ça ne marche pas, je suis obliger de ré-écrire le code fournis par Apple dans chacune de mes sous-classes...
Si tu veux c'est un peu comme si on pouvais avoir des CustomFileManager qui soient des singletons(sans redéfinitions) par la magie de l'héritage (sinon ça sert à rien d'utiliser l'héritage 8--))
C'est plus clair ou pas trop ?Â
Cf l'archive jointe, à dézipper et à mettre à côté des autres "File Templates" dans "/Developer/Library/Xcode/File Templates/Cocoa/" (pour les applis Mac) et dans "/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/File Templates/Cocoa Touch Class/" pour l'avoir aussi pour les projets iPhone
Tu quittes et relance Xcode (quoique je me demande si c'est nécessaire?) et quand tu es ensuite dans un de tes projets et veux créer un singleton, tu fais File -> New File et dans les templates proposés tu auras un nouveau template de fichier "Objective-C Singleton Class". Tu rentres le nom de ton fichier et Xcode fait tout le reste t'as plus rien à taper.
soit deux classes Singleton1 et Singleton2 qui hérite de Singleton.
Singleton1 -> Singleton ->NSObject
Singleton2 -> Singleton ->NSObject
Je peux créer autant de sous classes que je veux, j'aurais toujours qu'une seule instance:
id monSingleton1=[Singleton1 sharedInstance];
et/ou
id monSingleton2=[Singleton2 sharedInstance];
Dans tous les cas monSingleton1==monSingleton2
Si tu veux deux instances différentes, alors ce n'est plus un singleton.
CQFD
C'est pas faux ???
comment faire alors pour partager le comportement de singleton à plusieurs classes différente ? :why?:
Oui c'est une bonne idée
cependant j'aimerais également que mes singletons partagent des variables et des méthodes qu'ils peuvent redéfinir...
Bon je sens que mes singletons vont devenir des classes normales comme ça il n'y aura plus de problèmes, l'implémentation de singleton ne doit pas se prêter à toutes ces histoires de partage de méthodes, variables et comportements...
Sinon la méthode d'Aligator marche très bien, j'appelle ça le multi héritage du pauvre ???
- une classe abstraite (non instanciable) ParentSingleton mutualisant des variables d'instance
- une ou plusieurs classes concrètes, qui seront des singletons, dérivant de ParentSingleton pour récupérer les variables d'instance communes
Il suffit de :
- ne pas implémenter sharedInstance dans ParentSingleton (et d'interdir le init si la class de self est ParentSingleton pour interdire son instanciation directe)
- réimplémenter juste sharedInstance dans chacune des sous-classes de ParentSingleton : chacune initialisant/renvoyant la variable gloable déclarée en "static", celle qui mémorise l'instance singleton dès qu'elle est créée... puisque justement tu vas en avoir besoin d'une différente pour chacune de tes sous-classes si tu veux que chaque sous-classe soit singleton (et donc n'avoir qu'une instance de SingletonEnfant1, et une seule instance de SingletonEnfant2, mais que ces deux SingletonEnfantN ne partagent pas pour autant la même instance singleton...
On a donc MutiSingleton qui gère 3 Singletons et BaseSingleton qui contient 3 Outlets statiques, ce qui permet aux 3 singletons d'accéder aux 3 textFields.
Résultat: on a une instance orpheline de BaseSingleton, celle instanciée au chargement du nib, mais ça tombe bien car on en a besoin pour initialiser les outlets statiques
Comme ça c'est pas mal
Mais bon c'est vrai que c'est un peu tortueux mon histoire :crackboom:-
Il me passe des trucs dans le ciboulot des fois... :fouf):
En tous cas on s'est bien amusé non ?
En effet, Apple nous fournit dans Xcode des modèles de classes (NSView subclass, UIViewController subclass, ...) mais rien ne nous empêche de rajouter nos propres modèles.
J'ai donc pris l'exemple d'Apple et en ai fait un copier/coller en remplaçant juste le nom en dur (Gizmo) par "FILEBASENAMEASIDENTIFIER" (j'ai pris modèle sur les pbfiletemplates existants). J'ai encapsulé ça dans un pbfiletemplate et voilà
Le principe d'installation est simple :
NB : Il est aussi possible de créer un lien symbolique (par exemple dans le répertoire des templates de l'iPhone, faire un lien pointant sur le pbfiletemplate du répertoire de OSX) pour éviter la duplication
Apparemment, il n'est même pas nécessaire de relancer Xcode : vous pouvez dès à présent choisir dans Xcode le menu "File > New File..." puis choisir ce nouveau template pour ajouter un singleton au projet ouvert.
Donnez un nom à votre fichier, il en déduira le nom de la classe singleton à créer et fera tout tout seul
[EDIT] Avec la pièce-jointe, c'est mieux ;D
Est-ce qu'il s'agit du fichier de ton post précédent... ?
Concernant les singleton, je dévie un peu de la discussion abordée jusqu'ici vers un aspect plus général. En lisant différentes discussions ici ou là , deux éléments reviennent souvent:
(1) l'utilité réelle d'un Singleton
(2) la façon d'implémenter un Singleton
(1)
Le but d'un singleton est de définir une classe dont une seule instance uniquement peut être créée. Un autre avantage est de pouvoir y accéder facilement de n'importe où dans l'application, mais ce ne devrait pas être un argument en faveur de la création d'un singleton.
L'argument est le suivant: si tout ce que l'on veut est avoir un accès partagé et facile à une instance, il suffit de créer une méthode +[UneClasse sharedClasse] ou +[UneClasse defaultClasse] (exemple: +[NSFileManager defaultManager]).
(2)
Une façon d'implémenter un singleton est donnée par Apple dans sa doc. Mais elle ne fait pas forcément l'unanimité...
Une implémentation donnée par Peter Hosey est celle donnée ci-dessous, qu'il juge plus correcte que celle d'Apple.
Je serais donc intéressé à en débattre sur un forum francophone. 8--)
Voir en complément cet article de Peter Hosey et celui-ci de BJ Homer
Pour ton alternative de code, j'ai pas le temps ce soi... heu matin (serait p'tet temps que j'aille me coucher non ?) mais je regarderai plus tard.
Je connaissais, et je trouve son implémentation particulièrement élégante, car elle permet de se passer totalement de synchronisation, +initialize étant appelé par le runtime Objective-C de façon totalement "thread safe".