其工作原理的根本原因是:
[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
] 都被声明为返回 type 的值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不是一种类型安全的语言,编译器在许多情况下会警告你潜在的问题,但它不会在所有情况下都这样做。