我在 Objective-C 中有以下基/派生类设置:
@interface ASCIICodeBase : NSObject {
@protected
char code_[4];
}
- (Base *)initWithASCIICode:(const char *)code;
@end
@implementation ASCIICodeBase
- (ASCIICodeBase *)initWithCode:(const char *)code len:(size_t)len {
if (len == 0 || len > 3) {
return nil;
}
if (self = [super init]) {
memset(code_, 0, 4);
strncpy(code_, code, 3);
}
return self;
}
@end
@interface CountryCode : ASCIICodeBase
- (CountryCode *)initWithCode:(const char *)code;
@end
@implementation CountryCode
- (CountryCode *)initWithCode:(const char *)code {
size_t len = strlen(code);
if (len != 2) {
return nil;
}
self = [super initWithCode:code len:len]; // here
return self;
}
@end
在标记为“此处”的行上,我收到以下 gcc 警告:
warning: incompatible Objective-C types assigning 'struct ASCIICodeBase *', expected 'struct CurrencyCode *'
这段代码有问题还是我应该有ASCIICodeBase
return id
?或者也许在“这里”行上使用强制转换?
Use (id)
作为返回值类型。
Objective-C 不支持协变声明。考虑:
@interface NSArray:NSObject
+ (id) array;
@end
现在,您可以致电+array
双方NSArray
and NSMutableArray
。前者返回一个不可变数组,后者返回一个可变数组。由于 Objective-C 缺乏协变声明支持,如果上面声明为返回(NSArray*)
,子类方法的客户端必须转换为`(NSMutableArray*)。丑陋、脆弱且容易出错。因此,使用泛型类型通常是最直接的解决方案。
所以...如果您声明一个返回特定类实例的方法,请显式进行类型转换。如果您声明一个将被重写的方法,并且该重写可能会返回一个子类and它返回子类的事实将暴露给客户端,然后使用(id)
.
指定初始化器的工作方式相同。一个-init*
方法可以返回几乎任何类型的实例,具体取决于实现的上下文(当然)。因此,初始化方法的返回类型是协变的,因此,您需要使用(id)
作为返回类型。
无需提交错误——已经有几个错误了。
请注意,LLVM 现在有一个instancetype
可以用来代替的关键字id
在像上面这样的声明中。它的意思是“这个方法返回一个传递一个实例isKindOfClass:
有效地测试其被调用的类”。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)