Strict Type Checking in Objective-C via Macros

前端 未结 3 1918
我在风中等你
我在风中等你 2021-01-15 16:08

Occasionally, during development/debugging, I want to ensure that an object is of a certain type:

PageTopBottom *newPage = [notification object];
assert([new         


        
相关标签:
3条回答
  • 2021-01-15 16:34

    The preprocessor only processes text; it has no knowledge of type, which is why it's sometimes considered 'dangerous'. The only way I could see doing it is wrapping the variable declarations in a macro, which I would strongly advise against, and probably wouldn't actually cut down on the code or complexity.

    Also, shouldn't you check the type before casting?

    0 讨论(0)
  • 2021-01-15 16:36

    Hmm, with Objective-C++ there are two options:

    1. Write a template function

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

    2. For a pointer X* x, use NSClassFromString([NSString stringWithUTF8String:typeid(*x).name()]).

    Without using C++, you might be able to use GCC extension typeof, but I'm not sure if [typeof(*x) class] is a legit operation...

    0 讨论(0)
  • 2021-01-15 16:54

    Is it possible to get information about a variable's declared type from the variable?

    No. By the time the program is running, that information is lost. In your case, newPage is just a 32 or 64 bit number that points to a bit of memory that holds an Objective-C object.

    I think your original unmacro'd version is the right thing to do here:

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

    That perfectly documents the assumption you are making i.e. that you assume newPage is an instance of PageTopBottom or one of its subclasses and it's completely clear to anybody who understands Objective-C. Your macro version slightly obfuscates that, in that somebody coming across it in the code might beleive it is asserting that newPage is a PageTopBottom and not one of its subclasses (you could change the name of the macro to prevent that, I suppose, but I just wouldn't bother).

    Edit

    What you could do is combine the declaration and assertion in one:

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

    which would work like this:

    DECLARE_AND_ASSERT_IS_KIND_OF_CLASS(PageTopBottom, newPage, [notification object]);
    
    0 讨论(0)
提交回复
热议问题