代码之家  ›  专栏  ›  技术社区  ›  Brock Woolf

我应该验证foundationapi容器中的对象吗?

  •  2
  • Brock Woolf  · 技术社区  · 15 年前

    用像这样的语言 C++ C# 创建包含时,例如 std::vector 或者 C级# list 在创建容器类型时,可以显式声明它:

    C++:

    std::vector<MyObject>
    

    C#:

    List<MyObject> list = new List<MyObject>();
    

    看看上面的代码,我立刻知道这些容器只能包含类型为的对象 MyObject

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

    目标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]];
    

    而不是像 NSDictionary NSArray 将存储并接受从 NSObject . 我发现这本身非常灵活,但我不能确定容器中的对象类型,我只能在 runtime 鉴于 c++ c# 我知道这一点 compile time 只要看看代码。

    在为容器类添加、使用和删除对象时,是否应该验证容器的内容( , NSSet 等)从苹果的 Foundation Framework ? 或者这在任何情况下都是可以的,验证会对性能造成很大的伤害吗

    NSDictionary *dict = [[NSDictionary alloc]init];
    [dict objectForKey:@"someKey"];    // return nil?
    
    3 回复  |  直到 15 年前
        1
  •  5
  •   Barry Wark    15 年前

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

    if([obj respondsToSelector:@selector(myMethod)]) {
      [obj myMethod];
    }
    

    obj 属于某个类的层次结构。

        2
  •  2
  •   David    15 年前

    这似乎是避免检查从集合中获取的对象类型的“Objective-C方法”。当然,这是否好还有争议,但我认为这是一个总主题的一部分,即更愿意考虑对象响应的消息,而不是对象本身。

    这方面的一个例子是 ...Value stringValue intValue 等)许多对象响应的消息。同样值得注意的是 id 多样性。

        3
  •  0
  •   Kendall Helmstetter Gelner    15 年前

    我想说Objective-C中的模式是在一个容器中只存储一种类型的对象—而且您几乎总是可以确定容器中要存储什么。这就是为什么在实践中很少有人真正花时间检查收藏的内容。当我确实想验证某个东西时,我通常使用isKindOfClass:和一个正确类型的对象来保存集合中的一个项。

    如果您真的出于某种原因关心类型化,那么创建一个包装类来实现objectAtIndex:和其他常见的NSArray方法的类型化版本是非常容易的—注意,我不是在讨论NSArray的子类或任何其他集合,只是一个具有类似消息名称的对象。这类东西可以是很多用途的一个插件,您可以随时添加一个fall-through方法来访问backing集合。但我认为这比它的价值要麻烦得多,并且远离了语言。

    在实践中,在许多应用程序中,我几乎从未看到“数组中对象类型错误”会成为一个问题。

    对于一个接受typeID参数的方法,我更倾向于在使用前检查类型,因为这些方法倾向于接受范围更广的对象。