Question

Je suis tombé sur un étrange problème aujourd'hui. J'ai créé une sous-classe de UIView et ajouté une seule méthode au code de modèle fourni par xcode.

@interface FloatView : UIView {

}
- (void)floatTest:(CGFloat)x;
@end

- (void)floatTest:(CGFloat)x {
  NSLog(@"float was %f", x);
}

Ensuite, dans mon appDélégué, j'avais un code comme celui-ci:

UIView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];

Assez simple, non? Qu'est-ce que cela devrait imprimer? Je pensais que ce serait quelque chose comme "10.0000", mais non, il affiche "0.000000".

J'ai lutté avec cela pendant des heures, essayant de comprendre ce que je faisais mal, puis j'ai changé le code de mon appDelegate en

FloatView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];

Seulement alors, a-t-il imprimé le "10,0000" attendu. Pourquoi cela est-il ainsi? J'ai déclaré FloatView comme une sous-classe d'UIView. Ne devrais-je pas pouvoir affecter un objet FloatView à un pointeur UIView sans problème?

Même si floatView a été déclaré pointeur sur un UIView, il s’agit en réalité d’un floatView et devrait pouvoir gérer le message floatTest? Suis-je totalement hors de la base ici?

Était-ce utile?

La solution

En fait, le polymorphisme fonctionne comme prévu. Si cela ne fonctionnait pas, rien n'aurait été imprimé (dans votre exemple, 0,0000 est en cours d'impression). En réalité, votre instance répond effectivement au message testFloat: 10.0f , car le compilateur ne peut pas voir la déclaration de la méthode de manière statique (comme la classe UIView ne le déclare pas). méthode), elle suppose que votre méthode prend ... en argument et retourne id .

Lorsque CGFloat est passé à une méthode qui attend un nombre variable d'arguments ( ... ), il est promu en double . Ainsi, la méthode de réception reçoit un argument double et pense que c'est un float et elle ne s'imprime pas correctement.

Vous pouvez vérifier ce problème en remplaçant la ligne NSLog par:

NSLog(@"%f", *(double*)&x);

Lorsque le compilateur envoie le message à FloatView * plutôt qu'à un UIView * , il peut trouver la signature exacte de la méthode. Il peut voir qu'il attend réellement CGFloat et ne favorise pas l'argument en double . En conséquence, cela fonctionne correctement.

De plus, si UIView * contenait la déclaration de la méthode prenant un CGFloat , le compilateur appellerait la méthode de manière appropriée. Pour résumer, ce n'est pas un problème de polymorphisme; c'est un problème de signature de méthode manquante.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top