我有很多看起来像这样的代码:
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
无关的对象,我不确定我是不是在处理未定义的行为。
(不,我不能使用超类或接口,因为我实际上无法控制所有返回的类。)
答案 0 :(得分:5)
你可以做到。什么都没有定义。唯一的危险是,如果类型错误并且您忘记检查类型,则可能由于无法识别的选择器异常而崩溃。
在已编译的代码中,id
,MyClass *
和NSString *
没有区别,它们只是指向ObjC对象的指针。
答案 1 :(得分:2)
只要所有类型的返回对象符合NSObject
协议(从NSObject
类继承的类),就可以安全地使用isKindOfClass:
方法。
因此,请确保getObject()
方法仅返回从NSObject
继承的objective-c类
修改强>
虽然编译器很好用,但@Eiko提到有人阅读代码可能会认为isKindOfClass:
检查是不必要的。最好使用前面的代码让读者知道getObject()
也可能返回其他类型的对象。
答案 2 :(得分:2)
两个版本都可以使用。第一个感觉很笨,但第二个也存在问题:将某些东西放入特定类型的变量中意味着知道它的类型,并且检查看似已知的东西的类已经看起来多余了。如果有人(可能是你)明年查看该代码,他可能会发现班级检查是多余的并将其删除。
我一直处于类似的情况,我使用了一个帮助方法,它给出了一个正确的类型结果或者没有,即
-(Rectangle)getRectangleObject {
id data = getObject();
if ([data isKindOfClass:[Rectangle class]]) return data;
return nil;
}
这简化了代码并清楚地传达了意图。 如果需要多种不同的类型检查,可以使用多种方法,或者将类传递给此辅助方法。
答案 3 :(得分: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
的子类,则第一个条件将为true。因此,该对象将保存为MyClass1
对象。如果是这种情况,您需要建立优先级并将它们相应地放在嵌套的if-else-if语句中。