Subclassing und Gießen in Objective C
-
06-07-2019 - |
Frage
Ich kam in einem seltsamen Problem heute. Ich habe eine Unterklasse von UIView und hinzugefügt nur 1 Verfahren auf den von Xcode bereitgestellt Template-Code.
@interface FloatView : UIView {
}
- (void)floatTest:(CGFloat)x;
@end
- (void)floatTest:(CGFloat)x {
NSLog(@"float was %f", x);
}
Da ist in meinem AppDelegate hatte ich Code wie folgt:
UIView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];
Ganz einfach, nicht wahr? Was soll diese ausdrucken? Ich dachte, es wäre so etwas wie „10.0000“, aber nein, es ausdruckt „0.000000“.
ich mit dieser rang stundenlang versucht, herauszufinden, was ich tat, falsch, und dann änderte ich den Code in meinem AppDelegate zu
FloatView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];
Erst dann hat es die erwarteten „10.0000“ ausdrucken. Warum ist das so? Ich habe FloatView als Unterklasse von UIView erklärt, soll ich nicht in der Lage ein FloatView Objekt zu einem UIView Zeiger ohne Probleme zuweisen?
Auch wenn floatView einen Zeiger auf eine UIView erklärt wurde, ist es wirklich ein floatView und es sollte die floatTest Nachricht verarbeiten können? Bin ich total weg Basis hier?
Lösung
Eigentlich Polymorphismus funktioniert wie erwartet. Wenn es nicht funktioniert, würde nichts gedruckt wurde (in Ihrem Beispiel 0,0000 gedruckt wird). Die Sache ist, während die Instanz tatsächlich reagiert Nachricht an testFloat:10.0f
, da der Compiler nicht statisch die Methodendeklaration sehen kann (als UIView
Klasse nicht, ein solches Verfahren nicht erklären), geht davon aus, dass Ihre Methode als Argument und gibt ...
id
nimmt.
Wenn CGFloat
an eine Methode übergeben wird, die variable Anzahl von Argumenten (...
) erwartet, wird es gefördert double
. Somit wird das Empfangsverfahren ein double
Argument übergeben und denkt, dass es ein float
ist und es nicht richtig gedruckt bekommt.
Sie können dieses Verhalten überprüfen, indem NSLog
Linie auf sich ändernde:
NSLog(@"%f", *(double*)&x);
Wenn der Compiler die Nachricht sendet eher FloatView*
als ein UIView*
, kann er die genaue Signatur der Methode finden. Es kann es wirklich sehen CGFloat
erwartet und fördert nicht das Argument double
. Als Ergebnis funktioniert es einwandfrei.
Außerdem, wenn UIView*
die Methode Erklärung enthalten, die eine CGFloat
nahm, würde der Compiler die Methode in geeigneter Weise nennen. Um es zusammenzufassen, ist dies nicht ein Polymorphismus Problem ist; es ist eine fehlende Signatur der Methode Ausgabe.