Objective-C dynamic_cast?

Существует ли Objective-C эквивалент С++ dynamic_cast?

Его можно подделать, используя это:

MyClass *safeObject = [object isKindOfClass: [MyClass class]]
                      ? (MyClass *)originalObject : nil;

Но это много кода для ввода, даже если мне не нужно вводить его часто.

Я немного ржавый, так что это может быть не совсем правильно, но я считаю, что эквивалент в С++ будет:

MyClass safeObject = dynamic_cast<MyClass>(orginalObject);

Контекст здесь - это блок, где параметр определяется как тип более общего класса, но в этом блоке я "знаю" его конкретный подкласс. Тем не менее, я не хочу просто бросать его вслепую с помощью (MyClass *)originalObject и игнорировать теоретически возможную ошибку.

Чтобы быть ясным, хотя мне бы понравился dynamic_cast, я был бы доволен альтернативным подходом к безопасному обращению с этим делом.

Ответ 1

Если вы хотите использовать Objective-C ++, вы можете легко это записать:

template<typename T> inline T* objc_cast(id from) {
    if ([from isKindOfClass:[T class]]) {
        return static_cast<T*>(from);
    }
    return nil;
}

Это должно вести себя точно как dynamic_cast<> за исключением объектов obj-c.


Если вы хотите придерживаться ванильного Obj-C, вы можете получить аналогичное поведение с методом класса на NSObject:

@interface NSObject (Cast)
+ (instancetype)cast:(id)from;
@end

@implementation NSObject (Cast)
+ (instancetype)cast:(id)from {
    if ([from isKindOfClass:self]) {
        return from;
    }
    return nil;
}
@end

Эта версия просто не так хороша в использовании, так как вы должны сказать что-то вроде

UIButton *button = [UIButton cast:someView];

В обеих версиях результирующее значение nil, если сбой выполняется.

Ответ 2

Попробуйте этот макрос:

#define objc_dynamic_cast(obj, cls) \
    ([obj isKindOfClass:(Class)objc_getClass(#cls)] ? (cls *)obj : NULL)

А также не забывайте

#include <objc/runtime.h>

Используйте его как:

MyClass *safeObject = objc_dynamic_cast(originalObject, MyClass);

Ответ 3

  • Я не думаю, что есть.
  • Я думаю, что место для ошибки здесь довольно мало.
  • Но если вы настаиваете, макрос будет работать нормально?