Die zugrunde liegenden Gründe dies funktioniert, ist eine Kombination von:
[1] Objective-C (und C) wird bei der Kompilierung nicht stark typisiert. Während Warnungen vom Compiler erzeugt werden können, können sie normalerweise durch (manchmal unsichere) Casts zum Schweigen gebracht werden. Ihre Zuweisung ist in diesem Fall ungültig, da Sie eine Blockreferenz zuweisen, die angibt, dass einen mit NSNumber *
kompatiblen Argumentwert für eine andere Blockreferenz erfordert, die nur einen mit id
kompatiblen Argumentwert erfordert. Dieser Typ ist unsicher und führt manchmal zu Laufzeit Fehlern, siehe unten.
[2] Die Objective-C-Laufzeitnachrichtenübergabe ist dynamisch, dh der Zielcode für eine Nachricht wird ermittelt, während der Code ausgeführt wird. Dies bedeutet, dass alle Ihre Verwendungen von number
im Block nicht spezifisch für NSNumber
sind, wenn Sie eine NSDate
zur Laufzeit übergeben geeignete Methoden sind immer noch dynamisch lokalisiert. ändern jedoch Ihre bar
zu:
void (^bar)(NSNumber *) = ^(NSNumber *number)
{
NSLog(@"Value is %@, class is %@, int value is %d.", number, [number class], [number intValue]);
};
und Sie werden Laufzeit Fehler sehen.
[3] Beide [NSNumber numberWithInt:10]
und [NSDate date
] deklariert Werte vom Typ zurückzukehren id
, nicht NSNumber *
& NSDate *
wie man erwarten könnte. Dies bedeutet, dass Sie nicht foo
brauchen, können Sie einfach eingeben:
bar([NSDate date]);
und das gleiche Ergebnis ohne Warnungen bekommen ... Als weiteres Beispiel betrachten dies:
NSNumber *num = [NSNumber numberWithInt:3];
NSDate *date = num; // produces a warning
id erase = num; // erase type info and do...
date = erase; // effectively the same assignment, no warning
Nehmen Weg : Objective-C ist nicht eine Art sichere Sprache, der Compiler wird Sie in vielen Fällen vor möglichen Problemen warnen, aber es wird in allen Fällen nicht tun.
Ausgabe _ist_, oder Ausgabe _wäre be_? Denn wenn Sie getestet haben und das ist die tatsächliche Ausgabe, dann ist es erlaubt. – zneak
FYI das heißt * [Kovarianz und Kontravarianz] (http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29) *. –
Ich würde stattdessen void (^ bar) (id) verwenden, wenn Sie es so verwenden würden. – Cthutu