通过宏检查Objective-C中的严格类型

时间:2011-10-20 15:23:09

标签: objective-c macros

有时,在开发/调试期间,我想确保某个对象属于某种类型:

PageTopBottom *newPage = [notification object];
assert([newPage isKindOfClass:[PageTopBottom class]]);

我已经参与了这个

#define assertType(_var_, _class_) assert([_var_ isKindOfClass:[_class_ class]])

PageTopBottom *newPage = (id)[notification object];
assertType(newPage, PageTopBottom);

但是现在我想,如果可能的话,只需使用

assertType(newPage)

是否可以从变量中获取有关变量声明类型的信息?

我并没有肯定我正确地构思了这个问题,但任何让我能够用一个参数断言类型的答案都会很棒。

3 个答案:

答案 0 :(得分:4)

  

是否可以从变量中获取有关变量声明类型的信息?

没有。程序运行时,该信息将丢失。在您的情况下,newPage只是一个32或64位数字,指向一个包含Objective-C对象的内存。

我认为你原来的unmacro版本是正确的做法:

assert([newPage isKindOfClass:[PageTopBottom class]]);

这完美地记录了您所做的假设,即您假设newPage是PageTopBottom的实例或其子类之一,并且对任何了解Objective-C的人来说都是完全清楚的。您的宏版本稍微混淆了这一点,因为在代码中遇到它的人可能相信它断言newPage是PageTopBottom而不是其子类之一(您可以更改宏的名称以防止这种情况,我想,但是我只是不会打扰。)

修改

你可以做的是将声明和断言结合在一起:

#define DECLARE_AND_ASSERT_IS_KIND_OF_CLASS(T, V, I)    T* V = (T*)(I); assert([(V) isKindOfClass: [(T) class])

会像这样工作:

DECLARE_AND_ASSERT_IS_KIND_OF_CLASS(PageTopBottom, newPage, [notification object]);

答案 1 :(得分:2)

嗯,使用Objective-C ++有两种选择:

  1. 编写模板函数

    template void assertType(T * obj){...}

  2. 对于指针X* x,请使用NSClassFromString([NSString stringWithUTF8String:typeid(*x).name()])

  3. 如果不使用C ++,您可以使用GCC扩展typeof,但我不确定[typeof(*x) class]是否属于合法操作......

答案 2 :(得分:1)

预处理器只处理文本;它不知道类型,这就是为什么它有时被认为是“危险的”。我能看到的唯一方法是将变量声明包装在宏中,我强烈建议不要这样做,并且可能实际上不会减少代码或复杂性。

另外,你不应该在投射之前检查类型吗?