Строгая проверка типов в Objective-C с помощью макросов - PullRequest
2 голосов
/ 20 октября 2011

Иногда во время разработки / отладки я хочу убедиться, что объект имеет определенный тип:

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)

Можно ли получить информацию о объявленном типе переменной из переменной?

Я не уверен, что правильно формулирую вопрос, но любой ответ, который даст мне возможность assertType с одним параметром, был бы хорош.

Ответы [ 3 ]

4 голосов
/ 20 октября 2011

Можно ли получить информацию о объявленном типе переменной из переменной?

Нет. К тому времени, когда программа работает, эта информация теряется. В вашем случае newPage - это просто 32- или 64-битное число, указывающее на часть памяти, которая содержит объект Objective-C.

Я думаю, что ваша оригинальная версия unmacro'd является правильной вещью здесь:

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]);
2 голосов
/ 20 октября 2011

Хм, в Objective-C ++ есть два варианта:

  1. Написать шаблон функции

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

  2. Для указателя X* x используйте NSClassFromString([NSString stringWithUTF8String:typeid(*x).name()]).

Без использования C ++ вы можете использовать расширение GCC typeof, но я не уверен, является ли [typeof(*x) class] допустимой операцией ...

1 голос
/ 20 октября 2011

Препроцессор обрабатывает только текст; он не знает типа, поэтому его иногда считают «опасным». Единственный способ, которым я мог убедиться в этом, - это обернуть объявления переменных в макрос, что я настоятельно рекомендую, и, вероятно, фактически не уменьшит код или сложность.

Кроме того, разве вы не должны проверять тип до кастинга?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...