これが機能する根本的な理由は、次の組み合わせです。
[1] Objective-C(およびC)は、コンパイル時に強く型付けされません。警告はコンパイラーによって生成される場合がありますが、通常は(タイプが安全でない場合もある)キャストによって消音される可能性があります。この場合の割り当ては無効です。これは、と互換性のある引数値が必要であると宣言するブロック参照を、と互換性のある引数値がNSNumber *
必要であると宣言するだけの別のブロック参照に割り当てるためid
です。これはタイプが安全ではなく、ランタイムエラーが発生することがあります。以下を参照してください。
[2] Objective-Cのランタイムメッセージパッシングは動的です。つまり、メッセージのターゲットコードは、コードの実行時に決定されます。これは、ブロック内でのすべての使用が実行時に渡すときにnumber
非固有であるため、適切なメソッドが動的に配置されることを意味します。ただし、次のように変更してください。NSNumber
NSDate
bar
void (^bar)(NSNumber *) = ^(NSNumber *number)
{
NSLog(@"Value is %@, class is %@, int value is %d.", number, [number class], [number intValue]);
};
ランタイムエラーが表示されます。
[3][NSNumber numberWithInt:10]
と]の両方が、予想どおり&ではなく[NSDate date
、タイプの値を返すように宣言されています。これは、あなたが必要としないことを意味します、あなたはただタイプすることができます:id
NSNumber *
NSDate *
foo
bar([NSDate date]);
警告なしで同じ結果が得られます...さらなる例として、これを検討してください。
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
道を譲る:Objective-Cはタイプセーフな言語ではありません。コンパイラは多くの場合、潜在的な問題について警告しますが、すべての場合にそうなるわけではありません。