Cada vez que implemento un método en mi propio código que pueda aceptar o devolver objetos de más de una clase, siempre trato de usar la superclase más específica disponible. Por ejemplo, si fuera a implementar un método que pudiera devolver un NSArray * o un NSDictionary * según su entrada, le daría a ese método un tipo de devolución de NSObject *, ya que esa es la superclase común más directa. He aquí un ejemplo:¿Por qué utilizar (id) en una firma de método cuando (NSObject *) sería más preciso?
@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
me he dado cuenta de muchos casos en Fundación y otras API donde los usos de Apple (id) en ciertas firmas de método cuando (NSObject *) sería más preciso. Por ejemplo, aquí está un método de NSPropertyListSerialization:
+ (id)propertyListFromData:(NSData *)data
mutabilityOption:(NSPropertyListMutabilityOptions)opt
format:(NSPropertyListFormat *)format
errorDescription:(NSString **)errorString
Los posibles tipos de retorno de este método son NSData, NSString, NSArray, NSDictionary, NSDate y NSNumber. Me parece que un tipo de devolución de (NSObject *) sería una mejor opción que (id), ya que la persona que llama podría llamar a los métodos de NSObject como retener sin un tipo de conversión.
Generalmente trato de emular los modismos establecidos por los marcos oficiales, pero también me gusta entender qué los motiva. Estoy seguro de que Apple tiene alguna razón válida para usar (id) en casos como este, pero simplemente no lo estoy viendo. ¿Qué me estoy perdiendo?
NSProxy no es un objeto NSObject. NSObject no es la única clase de raíz, por lo que no es una suposición segura de que todo será una subclase de ella. –