有时,在开发/调试期间,我想确保某个对象属于某种类型:
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)
是否可以从变量中获取有关变量声明类型的信息?
我并没有肯定我正确地构思了这个问题,但任何让我能够用一个参数断言类型的答案都会很棒。
答案 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 ++有两种选择:
编写模板函数
template void assertType(T * obj){...}
对于指针X* x
,请使用NSClassFromString([NSString stringWithUTF8String:typeid(*x).name()])
。
如果不使用C ++,您可以使用GCC扩展typeof
,但我不确定[typeof(*x) class]
是否属于合法操作......
答案 2 :(得分:1)
预处理器只处理文本;它不知道类型,这就是为什么它有时被认为是“危险的”。我能看到的唯一方法是将变量声明包装在宏中,我强烈建议不要这样做,并且可能实际上不会减少代码或复杂性。
另外,你不应该在投射之前检查类型吗?