【问题标题】:Strict Type Checking in Objective-C via Macros通过宏在 Objective-C 中进行严格的类型检查
【发布时间】:2011-10-20 15:23:08
【问题描述】:

有时,在开发/调试过程中,我想确保一个对象属于某种类型:

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)

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

我不确定我是否正确地构建了问题,但任何能让我能够使用一个参数断言类型的答案都会很棒。

【问题讨论】:

    标签: objective-c macros


    【解决方案1】:

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

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

    我认为您的原始非宏版本是正确的做法:

    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]);
    

    【讨论】:

    • 太棒了,谢谢。我至少现在将我的宏更改为ASSERT_IS_KIND_OF_CLASS。如果可能的话,我有点不想弄乱声明,因为一旦不再需要断言,我就会删除它们。
    • 嗨,如果您认为我应该提出一个单独的问题,请告诉我:如果问题是将参数与方法的签名进行比较怎么办?换句话说,做一个严格的类型参数检查...
    • @Yar:是的,我认为是单独的问题。
    【解决方案2】:

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

    1. 编写模板函数

      模板 void assertType(T* obj) { ... }

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

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

    【讨论】:

    • 谢谢@Yuji。我不确定这是否正确,但问题是关于objective-c。我可以混音吗?
    • 是的,只需将文件扩展名更改为.mm 而不是.m。然后你可以混合使用 Objective-C 和 C++。并不是说两个类系统是统一的……只是两者都可以用。
    【解决方案3】:

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

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

    【讨论】:

    • 我不确定你在施法之前还是之后断言是否重要,因为无论如何你都会爆炸 :) 谢谢+1
    猜你喜欢
    • 2010-09-27
    • 2019-07-27
    • 2020-08-20
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    • 1970-01-01
    • 2012-02-21
    • 2011-06-10
    相关资源
    最近更新 更多