Objectif-C Type Inference
-
21-09-2019 - |
Question
D'accord, j'ai le sentiment que vous soyez guys'll en mesure de signaler rapidement pourquoi je suis si confus à ce sujet, mais j'ai une question de savoir pourquoi ce qui suit ne donne pas lieu à une erreur du compilateur ou un avertissement:
NSString * intValue = [ NSString stringWithFormat:@"int = %i", [ [ self.selectedObject valueForKey:name ] integerValue ] ];
selectedObject
est un NSObject
et name
se trouve être le nom d'un @property
de type int
.
Ce qui me embarrasse est pourquoi le compilateur est parfaitement prêt à supposer que le résultat de retour de [ self.selectedObject valueForKey:name ]
est de type NSNumber *
(sans typecasting il) afin d'enchaîner le message avec un appel à integerValue
.
De toute évidence, KVC se termine non un type d'objet « numéro » dans NSNumber
, mais il n'y a aucun moyen pour le compilateur de savoir que -valueForKey:
retournera un NSNumber *
dans ce cas particulier.
Pourquoi ne pas ce résultat dans un avertissement du compilateur le long des lignes de « id
peut ne pas répondre à« -integerValue
»?
La solution
J'espère que je me trompe pas: En effet, id
est « spéciale ». Les objets du type de id
peut être envoyé un message que vous voulez, il n'y a pas de vérification fait par le compilateur et tout sera vérifiée dans l'exécution. Ou, en d'autres termes, le type de id
est la partie de l'objectif-C, alors que tous les autres types « typage dynamique » (comme NSObject
) sont la partie « typage statique ».
De cette façon, vous pouvez choisir où vous souhaitez utiliser le typage statique, et où vous voulez utiliser le typage dynamique. Il est parfaitement légal de faire quelque chose comme ceci:
id str1 = @"Hello";
id str2 = [str1 stringByAppendingString:@", world"];
Mais généralement, vous tapez les chaînes « bien » comme NSString
s, parce que vous obtenez la commodité de la compilation vérification de type statique, et seule station à typage dynamique où le statique obtiendrait de la manière, comme dans la situation valueForKey
.
Autres conseils
Le temps est passé et nous avons une meilleure inférence de type grâce à la __auto_type
disponible depuis Xcode 8. Alors maintenant, vous pouvez le faire
#define let __auto_type const
#define var __auto_type
let a = @[@"pew pew"];
var b = 2;
b = a; //compiler warning "Incompatible pointer to integer conversion assigning to 'int' from 'NSArray *__strong const'"
En fait, je l'ai aimé ce si bien que je fait cela comme un pod pour plus de commodité.
pod 'SwiftyObjC'