2009-04-08 7 views
2

En Java, il est très facile de coder la conception suivante:modèle d'objet nul en Objective-C

public abstract class Pizza { 
    public static final Pizza.NULL = new Pizza() { 
     /* "null" implementations */ 
    } 

    /* actual/abstract implmentations */ 
} 

Quelle est la méthode préférée pour atteindre le même scénario efficace Objective-C? J'ai été incapable de trouver de la documentation sur le sujet, et j'ai essayé quelques scénarios différents avec static const, #define etc mais aucun d'entre eux ne semble fonctionner aussi bien que la méthode Java ci-dessus. Je voudrais éviter d'écrire une classe NullPizza concrète qui a une méthode statique pour obtenir l'instance singleton, car il semble plus approprié que ce soit une propriété/champ final de l'interface de plus haut niveau. Bien que je comprenne comment le modèle NULL serait spécifiquement géré en raison de la méthode unique d'Obj-C de gérer les appels de méthode à «nil», qu'en est-il d'autres instances communes statiques, comme Response.YES et Response.NO? (Voir les commentaires pour la discussion.)

+0

Impossible de compiler ce code sur Java. Qu'est-ce que je fais de mal? –

Répondre

-1

Pour vos Response.YES et Response.NO, je suppose que vous avez des instances que vous faites vouloir changer, plutôt que de simplement rendre toutes les propriétés de la réponse en lecture seule. Un motif courant dans Cocoa est d'avoir des versions immuables et mutables d'une classe (NSArray versus NSMutableArray). Pour votre exemple de réponse, il serait logique d'avoir une classe Response immuable qui a les méthodes YES et NO statiques, et une sous-classe MutableResponse qui expose les setters pour les moments où vous voulez que les objets les changent. Est-ce que cela couvre votre deuxième exemple?

12

Ce type de modèle n'est pas nécessaire en Objective-C car il n'est pas considéré comme une erreur d'exécution pour signaler une instance nulle d'une classe. Si la méthode a un type de retour défini, il existe des retours définis à partir de la messagerie d'un objet nul (par exemple, les méthodes qui renvoient un entier renvoient 0 lors de la messagerie d'un objet nul).

+0

C'est vrai, j'utilisais simplement le NOP comme exemple. Que feriez-vous dans une situation où il y a deux implémentations par défaut d'une classe, disons Réponse, et vous vouliez un Response.YES et un Response.NO qui étaient statiques, des implémentations finales? –

+0

Il suffit de créer des méthodes d'usine qui renvoient ces instances, comme + [NSDecimalNumber zero] et + [NSDecimalNumber un]. BTW il n'y a pas de «finale» dans ObjC. –

+0

C'était mon plan initial, mais comment vous assurer que l'instance retournée n'est pas modifiée? L'instance doit être un singleton, donc vous ne perdez pas de mémoire en retournant une nouvelle instance à chaque fois, mais si chaque appel à [Pizza null] renvoie la même référence, cet objet ne pourrait-il pas être modifié? –

2

Il y a deux choses qui peuvent aider ici. Le premier est nil, l'équivalent Objective-C du pointeur Java NULL - il peut effectivement recevoir des messages et y répondre. Il renverra toujours nil si la valeur de retour est un objet et 0 si la valeur de retour est un type primitif. Par conséquent, si le comportement Null de votre objet est "ne rien faire", vous pouvez facilement utiliser nil comme valeur Null.

L'autre élément utile est lorsque vous avez besoin de stocker un espace réservé ou une valeur null dans un objet conteneur. En général, ces exceptions génèrent des exceptions si vous tentez d'ajouter nil en tant que valeur. Au lieu de cela, vous pouvez utiliser le singleton +[NSNull null], qui ne fait rien sauf agir comme un objet "cet espace intentionnellement laissé vide".

Avec ces deux armes à votre disposition, il devrait y avoir aucune raison d'écrire une instance nulle d'une classe personnalisée :-)

+0

Voir le commentaire sur Jason. :) –

+0

voir mon commentaire en réponse à votre commentaire :-) et maintenant laissons le meta-thread ... ;-) –

0

Je ne pense pas qu'il existe un moyen facile de fournir cette implémentation. Vous demandez que quelque chose qui est une fonctionnalité de langage de Java soit implémentée dans Objective-C - vous pouvez le faire mais vous devez écrire le code qui est dans le runtime Java vous-même - rien ne vous empêche de le faire mais c'est C'est un peu comme si on demandait "Comment afficher un menu par fenêtre" UI dans Cocoa "de style Windows - vous pouvez le faire mais il n'est pas fourni gratuitement à partir du framework. Ou, "comment puis-je facilement implémenter la gestion du pointeur nil d'Objective-C en Java?"

Si vous voulez vraiment voir ce type de fonctionnalité, je pense que vous devriez suivre le modèle de conception NSArray/NSMutableArray Déclarer une superclasse qui peut gérer tous vos cas particuliers:.

@interface NullPizza : NSObject 
{ 
} 
- (BOOL)areYouANullPizza; 
@end 

et sous-classe avec votre vraie pizza et inclure une méthode de classe newNullPizza (ce qui est le sucre juste syntaxe):.

@interface Pizza : NullPizza 
{ 
} 

+ (Pizza*)Null; 
@end 

@implementation Pizza 
+ (Pizza*)newNullPizza 
{ 
    return [[NullPizza]alloc init]; // Singleton code left as an exercise. 
} 

- (BOOL)areYouANullPizza; 
{ 
    return NO; 
} 
@end 

Notez que si vous vouliez mettre en œuvre une méthode +(Pizza*)NULL sur Pizza vous devez autoRelease la nouvelle NullPizza vous créez

Avis de non-responsabilité, j'ai tapé ce code directement dans SO. Je serais surpris si cela compile mais vous avez l'idée.