Question de débutant Objective-C. Étant donné le code (fictif) suivant:
id mysteryObject = [anotherObject mysteriousMethod];
Comment puis-je déterminer au moment de l'exécution quelle classe mysteryObject
est?
Question de débutant Objective-C. Étant donné le code (fictif) suivant:
id mysteryObject = [anotherObject mysteriousMethod];
Comment puis-je déterminer au moment de l'exécution quelle classe mysteryObject
est?
Dans un typées dynamiquement langue comme l'Objective-C (ou Python ou Ruby), vous n'avez pas envie de savoir quel type d'objet il s'agit. Il est souvent plus productif de penser que l'objet répond au message que vous souhaitez envoyer; si elle le fait, vous ne devriez pas vous soucier de ce que la classe qu'il instancie et si ça ne marche pas, vous devez traiter le cas, quelle que soit l'instance du type. Ceci est connu comme "duck typing"...si c'charlatans comme un canard, c'est un canard.
Vous pouvez tester si un objet répond à un message particulier (connu comme un sélecteur en Objective-C) comme ceci:
if([mysteryInstance respondsToSelector:@selector(messageIWishToSend)]) {
[mysteryInstance messageIWishToSend];
} else {
//handle case where instance doesn't respond to the desired message
}
Encore mieux que de tester pour chaque sélecteurs est de définir un @protocol
qui décrit l'API que vous souhaitez utiliser pour vos classes:
// MyProtocol.h
@protocol MyProtocol
- (void)methodInMyProtocol;
@end
//MyClass.h
#import "MyProtocol.h"
@interface MyClass <MyProtocol> {
}
- (void)methodInMyProtocol;
@end
Vous pouvez tester si une instance implémente l' MyProtocol
protocole comme ceci:
if([mysteryInstance conformsToProtocol:@protocol(MyProtocol)]) {
[mysteryInstance methodInMyProtocol];
} else {
// ...
}
Cette façon de faire est souvent mal à l'aise pour les gens venant de langages statiquement typés comme le Java ou le C++. Vous perdez le compilateur de vérifier types pour vous. Typage dynamique qui fait un grand nombre de choses plus facile, cependant, y compris les tests puisque vous pouvez facilement remplacer une instance avec une faux à la durée du test. Ainsi, la dynamique de la langue de l'approche est de tester plus et de se soucier de types moins. Vous avez une bonne couverture de tests unitaires, n'est-ce pas?
Si vraiment vous devez déterminer la classe d'une instance au moment de l'exécution (et vous avez vraiment n'avez pas besoin probablement de), vous pouvez utiliser -[NSObject isKindOfClass:]
pour tester si une instance est une instance d'une classe ou d'un quelconque de ses sous-classes ou -[NSObject isMemberOfClass:]
pour tester si une instance est une instance d'une classe particulière. Vous pouvez inspecter l' Class
objet directement comme le retour de l' -[NSObject class]
et vous pouvez obtenir le nom de la chaîne de l'instance de la classe avec NSStringFromClass([mysteryInstance class])
.
J'ai trouvé que je devais renvoyer id à id avec une méthode définie dans un @ protocole.
Par exemple, self.listeners est un tableau d'identifiants.
Si je fais ça ....
for(id<PropertyListener> listener in self.listeners) {
if ( [ [ listener class] respondsToSelector:@selector(propertyChanged:propertyName:)]) {
J'obtiens une erreur "Aucune méthode d'instance connue pour le sélecteur 'classe'". Pourtant, quand je lance l'identifiant d'un identifiant à l'autre, cela fonctionne ... Pourquoi je ne comprends pas.
[ ((id)listener) class] respondsToSelector ....
Voici la boucle complète ...
for(id<PropertyListener> listener in self.listeners) {
if ( [ [ ((id)listener) class] respondsToSelector:@selector(propertyChanged:propertyName:)]) {
[listener propertyChanged: self propertyName:@"thePropName"];
} else {
[listener propertyChanged: self];
}
}
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.