【发布时间】:2018-03-09 18:18:43
【问题描述】:
我知道我可以使用 __kindof 关键字来使用 Objective-C 的轻量级泛型,例如
NSArray<__kindof BaseClass*> *myArray;
这将消除将数组中的任何对象分配给派生类的任何警告。
但是,我有BaseProtocol,而不是BaseClass,例如我所有有问题的课程都将符合BaseProtocol,无论它们的基类如何。我想使用轻量级泛型来规定“我的数组由符合BaseProtocol 的元素组成,但它们可以是任何类”。
例如在 C# 中,我可以说:List<IMyInterface>,这意味着列表由实现 IMyInterface 接口的元素组成(我知道 C# 具有强大的泛型,而 Objective-C 只有轻量级的泛型,而没有防止编译,但你明白了)。
有没有办法在 Objective-C 上实现这个功能?
例如我要写
NSArray<__kindof id<MyProtocol>> //compiles, but as the generic argument is "id", it accepts any object, including invalid ones
或
NSArray<id<__kindof MyProtocol>> //doesn't compile
这可能吗?
更新:
这是一个完整的独立代码:
@protocol MyProtocol
@end
@interface MyClass : NSObject<MyProtocol>
@end
@implementation MyClass
@end
@interface AnotherClass : NSObject
@end
@implementation AnotherClass
@end
NSMutableArray<__kindof id<MyProtocol>> *myArray;
void test(){
MyClass *myClassInstance = [[MyClass alloc] init];
AnotherClass *anotherClassInstance = [[AnotherClass alloc] init];
myArray = @[].mutableCopy;
[myArray addObject:myClassInstance];
[myArray addObject:anotherClassInstance]; //i get warning. good.
MyClass *returnedInstance = myArray[0];
AnotherClass *anotherInstance = myArray[1]; //why don't I get a warning here?
}
【问题讨论】:
-
@Rob 对,我的错。固定的。 (关于第二条评论)
-
@Rob 我已经在一个新的干净项目中实现了一个示例,正如您所说,如果我尝试添加一个类型不符合协议的对象,我确实会收到警告。但即使我在我的主要项目中应用了确切的模式,我也没有收到警告。我没有玩过任何与警告相关的项目设置。可能是什么原因?
-
如果你去“report navigator”,你可以拉起编译日志,它说这是
-Wobjc-literal-conversion的结果。因此,返回第一个项目的构建设置并搜索“literal”,您将看到该设置(称为“Implicit Objective-C Literal Conversions”)。也许这是一个早于这些设置的旧项目。 -
@Rob 很有趣。该选项设置为“是”,在我的项目中,我尝试了
NSArray<SpecificClass<MyProtocol>*>*,然后我做了NSObject *x = myArray[0];,如果我理解正确,现在应该会给我警告,但事实并非如此。 -
在您上次的编辑中,您问为什么您没有收到关于您的新
AnotherClass *anotherInstance = myArray[1]示例的警告。在该特定示例中我也没有看到该警告,但是当我将NSArray声明更改为NSArray<__kindof SpecificClass<MyProtocol>*>*array;而不是NSArray<__kindof NSObject<MyProtocol>*>*array;或NSArray<__kindof id MyProtocol>*>*array;时会这样做。令我震惊的是,您的示例也应该产生警告。
标签: objective-c generics casting covariance