2010-10-17 4 views
2

J'ai une classe appelée AddressCard à partir d'un exemple dans "Programmation en Objective C", et j'implémente une méthode isEqual:.Strict vs loose typing lors du remplacement d'une méthode

La signature de cette méthode dans NSObject utilise un typage lâche pour le paramètre:

- (BOOL)isEqual:(id)anObject 

OTOH, l'exemple de code dans le livre utilise le typage strict:

- (BOOL) isEqual:(AddressCard *) aCard 

Je ne suis pas sûr comprendre parfaitement ce que le compilateur fait dans ce cas. J'ai essayé de comparer une AddressCard à un NSString ([aCard isEqual: @"Foo"]) en m'attendant à une erreur d'exécution (si le système utilise ma méthode) ou que le système appelle la version de IsEqual de NSObject.

Au lieu de cela, ma méthode a été appelée (même si le paramètre était un NSString et non un AddressCard) et a soulevé une exception lorsque mon IsEqual: a essayé d'appeler aa méthode spécifique à AddressCard:

- (BOOL) isEqual:(AddressCard *) aCard { 
    if ([name isEqualToString: [aCard name]] && /*here I get the error*/ 
     [email isEqualToString:[aCard email]]) { 
     return YES; 
    }else { 
     return NO; 
    } 
} 

Qu'est-ce qui se passe ? Comment sur Terre est un NSString étant passé à une méthode qui attend quelque chose d'autre? Est-ce que changer la signature d'une méthode est OK en la surchargeant?

Répondre

1

L'exécution distingue les messages par leur sélecteur. Toutes les méthodes portant le même nom ont le même sélecteur. Les arguments de méthode n'ont aucune influence sur le sélecteur. Dans votre cas, le sélecteur est isEqual:.

Ceci est d'Apple « L'Objective-C Programming Language » (Souligné par):

La routine de messagerie a accès à des implémentations de méthode que par sélecteurs, il traite toutes les méthodes avec le même sélecteur semblables. Il découvre le type de retour d'une méthode, et les types de données de ses arguments, à partir du sélecteur. Par conséquent, à l'exception des messages envoyés aux récepteurs statiquement typés, la liaison dynamique requiert que toutes les implémentations de méthodes nommées de manière identique aient le même type de retour et les mêmes types d'argument. (récepteurs typés statiquement sont une exception à cette règle, puisque le compilateur peut en apprendre davantage sur la mise en œuvre de la méthode du type de classe.)

En d'autres termes: changer la signature d'une méthode existante n'est pas bonne forme (OMI) mais c'est bien aussi longtemps que vous tapez statiquement les récepteurs de ces méthodes (dans votre cas, cela signifie que aCard doit être déclaré comme AddressCard *). Pour l'exécution, ce n'est pas un problème.

Malheureusement, vous ne mentionnez pas si le compilateur vous donne un avertissement parce que vous passez un NSString * où il attend un AddressCard *. Je m'attendrais à ce qu'il le fasse.

+0

Aucun avertissement du tout. Cela déclenche juste une exception dans l'exécution. – cfischer

+0

Je m'attendrais certainement à un avertissement aussi. Semble un peu bâclé ... – cfischer

+0

BTW, si je change la signature de ma méthode isEqual:, donc il correspond à NSObject Je reçois un avertissement: "Conflicting types for '- (BOOL) estEqual: (id *) aCard. ? O :-) – cfischer

1

Ma meilleure estimation: Tout le compilateur voit une méthode qui s'attend à ce qu'un pointeur soit appelé avec un paramètre pointeur. Pas de problèmes pour le compilateur.

Questions connexes