2

我有很多看起来像这样的代码:

id myObjectRaw = getObject();
if(![myObjectRaw isKindOfClass:[MyClass class]]) return nil;
MyClass * myObject = myObjectRaw;
...

这里id getObject()可以返回几种对象。然而,上面的代码对我来说感觉很笨拙。写这个安全吗?

MyClass * myObject = getObject();
if(![myObject isKindOfClass:[MyClass class]]) return nil;
...

编译器没有抱怨,但我不确定如果getObject返回一个与MyClass.

(不,我不能使用超类或接口,因为我实际上无法控制所有返回的类。)

4

4 回答 4

5

你能行的。没有什么未定义的。唯一的危险是,如果类型错误而你忘记检查类型,它可能会由于无法识别的选择器异常而崩溃。

在编译后的代码中idMyClass *NSString *没有区别,它们只是一个指向 ObjC 对象的指针。

于 2013-09-12T06:00:18.537 回答
2

只要所有类型的返回对象都符合NSObject协议(从类继承的NSObject类),使用isKindOfClass:方法是安全的。

所以确保getObject()方法只返回继承自的objective-c类NSObject

编辑

虽然编译器对此很好,但@Eiko 提到阅读代码的人可能会认为isKindOfClass:检查是不必要的。最好使用前面的代码让读者知道它getObject()也可能返回其他类型的对象。

于 2013-09-12T06:09:38.030 回答
2

两个版本都可以使用。第一个感觉很笨拙,但第二个也有问题:将某些东西放入特定类型的变量中意味着知道它的类型,而检查似乎已经知道的东西的类看起来是多余的。如果有人(可能是您)明年查看该代码,他可能会发现类检查是多余的并将其删除。

我也遇到过类似的情况,我使用了一个辅助方法,它给出了正确键入的结果或 nil,即

-(Rectangle)getRectangleObject {
   id data = getObject();
   if ([data isKindOfClass:[Rectangle class]]) return data;
   return nil;
}

这简化了代码并清楚地传达了意图。如果你需要几个不同的类型检查,你可以使用几个方法,或者将类传递给这个辅助方法。

于 2013-09-12T08:07:01.810 回答
0

当您使用时,id myObjectRaw您没有定义什么类型的对象myObjectRaw,因此编译器将不知道是否MyClass * myObject = getObject();是有效操作。编译器假定您知道自己在做什么。如果getObject()返回一个不同的对象MyClass或者它不是它的子类,您的应用程序可能会崩溃。这是一个运行时错误。

如果getObject()返回不同的对象,您应该期望至少有一个可以返回的对象类型的对象。如果需要处理不同的对象,您始终可以使用 if-else-if 指令,例如:

id myObjectRaw = getObject();

if([myObjectRaw isKindOfClass:[MyClass1 class]])
{
    MyClass1 objectClass1 = myObjectRaw;
}
else if([myObjectRaw isKindOfClass[MyClass2 class]])
{
    MyClass2 objectClass2 = myObjectRaw;
}

但是,如果返回的对象是一个MyClass2对象,并且这个类是子类的MyClass1第一个条件就会为真。因此,对象将被保存为MyClass1对象。如果是这种情况,您需要建立优先级并将它们相应地放在嵌套的 if-else-if 语句中。

于 2013-09-12T06:20:16.083 回答