【问题标题】:Objective-C dynamic_cast?Objective-C 动态转换?
【发布时间】:2012-05-11 19:53:14
【问题描述】:

是否存在与 C++ 的 dynamic_cast 等效的 Objective-C?

可以用这个来伪造:

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

但要输入的代码很多,即使我不需要经常输入。

我有点生疏,所以这可能不太正确,但我相信 C++ 中的等价物是:

MyClass safeObject = dynamic_cast<MyClass>(orginalObject);

这里的上下文是一个块,其中参数被定义为更通用的类的类型,但在这个块中我“知道”它是一个特定的子类。尽管如此,我不想只是盲目地使用(MyClass *)originalObject 进行投射,而忽略理论上可能出现的错误。

需要明确的是,虽然我喜欢 dynamic_cast,但我也很乐意采用另一种方法来安全处理此案。

【问题讨论】:

  • 在最坏的情况下,您可以为此编写一个宏。
  • Objective-C 是鸭式的。老实说,“复杂”的演员阵容有点反对这种语言。
  • 是的,我想我可能在这里问错了问题。无论我应该问什么问题,答案都是“只需使用NSAssert([object isKindOfClass: [MyClass class]], @"blahblah"),因为无论如何你都不会期待它”。 :)

标签: objective-c


【解决方案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&lt;&gt; 完全一样,除了 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

【讨论】:

  • 第二个例子正是我正在寻找的。而且非常简单。谢谢。
  • 这是对 instancetype 操作符的一个很好的使用,所以编译器和 Xcode 自动完成可以立即开始使用转换后的类型
【解决方案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);

【讨论】:

  • 希望您不介意,但我包装了您的宏并添加了 (cls *) 以满足编译器警告。做得好!由于 Xcode 在范围内的编辑,我犹豫是否在这里使用宏,但它似乎工作得很好。
  • 您是否介意添加一行来说明如何使用此宏(对于更环保的局外人)。谢谢。
  • 我加了一个。 (H2CO3:如果您觉得我弄乱了您的答案,请随时回复。只是想帮助未来的读者!)
  • 鉴于问题的性质,当无法安全地投射对象时,代码爆炸不是更好吗?
  • 是的,我认为这是解决问题的更好答案。不过,在这一点上,我试图公平对待我实际提出的问题。 :)
【解决方案3】:
  1. 我认为没有。
  2. 我认为这里的错误空间很小。
  3. 但如果你坚持,宏就行了?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-09
    • 1970-01-01
    • 1970-01-01
    • 2012-07-06
    • 2011-11-01
    • 2013-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多