我应该验证Foundation API容器内的对象吗?

Bro*_*olf 2 iphone macos cocoa objective-c core-foundation

在类似的语言中C++,C#当您创建包含诸如a std::vector或a C# list之类的语言时,在创建容器类型时显式声明容器类型:

C++:

std::vector<MyObject>
Run Code Online (Sandbox Code Playgroud)

C#:

List<MyObject> list = new List<MyObject>();
Run Code Online (Sandbox Code Playgroud)

看看上面的代码,我立即知道这些容器只能包含类型MyObject的对象,如果我尝试添加一个不属于这种类型的对象,编译器会抱怨.

由于Objective-C是一种动态语言,我们没有编译器的特权警告我们(因为它是完全有效但有潜在危险的事情):

Objective-C的:

NSDictionary *dict = [[NSDictionary alloc]init];
[dict setValue:[[SomeClass alloc]init] forKey:@"someClass"];
[dict setValue:[[NSMutableString alloc]init] forKey:@"mutableString"];
BOOL classIsSomeClass = [[dict objectForKey:@"someClass"] isKindOfClass:[SomeClass class]];
Run Code Online (Sandbox Code Playgroud)

相反,类似于NSDictionary或NSArray将存储和接受任何类型的对象继承自NSObject.我发现这本身非常灵活,但我无法确定容器中的对象类型我只能真正知道,runtime而我c++或者只是通过查看代码.c#compile time

当添加,使用及移除容器类对象(我应该确认容器的内容NSArray,NSSet,NSDictionary来自苹果等),基础架构?或者在所有情况下都可以,并且验证会损害性能吗?:

NSDictionary *dict = [[NSDictionary alloc]init];
[dict objectForKey:@"someKey"];    // return nil?
Run Code Online (Sandbox Code Playgroud)

Bar*_*ark 5

Objective-C的动态消息传递更像是Python或Ruby等动态语言.在这些语言中,标准范例通常被称为"鸭子打字".换句话说,如果一个对象实例像鸭子一样嘎嘎叫(即响应你正在发送的消息),它就是一只鸭子.在Objective-C中,可以在运行时通过对象继承层次结构之外的许多机制添加方法.因此,询问实例是否响应特定选择器更为常见:

if([obj respondsToSelector:@selector(myMethod)]) {
  [obj myMethod];
}
Run Code Online (Sandbox Code Playgroud)

而不是要问是否obj属于某一类的等级.

在大多数情况下,Objective-C开发人员不会进行此检查,除非他们从"未知"模块获取对象实例.相反,我们在很大程度上依赖于编译器警告(Objective-C编译器将警告将消息发送到不确定可以接收该消息的类型)和单元测试.在这种情况下,单元测试确认正确的对象进入集合并且您从集合中获得预期的类型可能会大大减轻您的恐惧.