Chaque fois que j'implémente une méthode dans mon propre code qui peut accepter ou retourner des objets de plus d'une classe, j'essaie toujours d'utiliser la superclasse la plus spécifique disponible. Par exemple, si j'allais implémenter une méthode qui pourrait retourner un NSArray * ou un NSDictionary * en fonction de son entrée, je donnerais à cette méthode un type de retour de NSObject *, puisque c'est la superclasse la plus directe. Voici un exemple:Pourquoi utiliser (id) dans une signature de méthode quand (NSObject *) serait plus précis?
@interface MyParser()
- (BOOL)stringExpressesKeyValuePairs:(NSString *)string;
- (BOOL)stringExpressesAListOfEntities:(NSString *)string;
- (NSArray *)parseArrayFromString:(NSString *)string;
- (NSDictionary *)parseDictionaryFromString:(NSString *)string;
@end
@implementation MyParser
- (NSObject *)parseString:(NSString *)string {
if ([self stringExpressesKeyValuePairs:string]) {
return [self parseDictionaryFromString:string];
}
else if ([self stringExpressesAListOfEntities:string]) {
return [self parseArrayFromString:string];
}
}
// etc...
@end
J'ai remarqué de nombreux cas dans Foundation et d'autres API où les utilisations d'Apple (id) dans certaines signatures de méthode quand (NSObject *) seraient plus précis. Par exemple, voici une méthode de NSPropertyListSerialization:
+ (id)propertyListFromData:(NSData *)data
mutabilityOption:(NSPropertyListMutabilityOptions)opt
format:(NSPropertyListFormat *)format
errorDescription:(NSString **)errorString
Les types de retour possibles de cette méthode sont NSData, NSString, NSArray, NSDictionary, NSDate et NSNumber. Il me semble qu'un type de retour de (NSObject *) serait un meilleur choix que (id), puisque l'appelant serait alors capable d'appeler des méthodes NSObject comme retain sans cast.
En général, j'essaie d'imiter les idiomes établis par les cadres officiels, mais j'aime aussi comprendre ce qui les motive. Je suis sûr que Apple a une raison valable d'utiliser (id) dans des cas comme celui-ci, mais je ne le vois tout simplement pas. Qu'est-ce que je rate?
NSProxy n'est pas un objet NSObject. NSObject n'est pas la seule classe racine, donc ce n'est pas une supposition sûre que tout sera une sous-classe. –