泛型:使用“ NSMutableArray <__ kindof超类*> *”类型的表达式初始化“ NSMutableArray <subclass * =“”> *”的不兼容指针类型

时间:2018-08-27 07:37:37

标签: objective-c generics

我具有此属性:

@property (nonatomic) NSMutableArray <__kindof superclass*> *items;

我用一个子类的对象填充它(由于__kindof应该没问题)。我这样检索数组:

NSMutableArray <__kindof subclass*> *items = holderObject.items;

但是现在我收到此编译器警告:

Incompatible pointer types initializing 'NSMutableArray<subclass *> *' with an expression of type 'NSMutableArray<__kindof superclass *> * _Nullable'

这不是__kindof应该为我们做的吗?我在这里做什么错了?

更新2:这仅适用于可变数组。

更新:这是一些显示警告的简单代码:

创建一个新类GenericsError.h:

@import UIKit;
@interface GenericsError : NSObject
@property (nonatomic) NSMutableArray <__kindof UIViewController*> *generics;
@end

在任何viewController中只需添加:

GenericsError *error = [GenericsError new];
NSMutableArray <ViewController*>* controllers = error.generics;

(用ViewController代替您所调用的viewController)。我没有添加或创建任何东西,只是得到了针对Generics-Error的编译器警告。

2 个答案:

答案 0 :(得分:0)

NSMutableArray的通用参数是不变的(它被声明为@interface NSMutableArray<ObjectType>而不是@interface NSMutableArray<__covariant ObjectType>@interface NSMutableArray<__contravariant ObjectType>)。这意味着类型参数必须完全匹配才能兼容。

这意味着NSMutableArray<NSString *> *不能分配给NSMutableArray<NSObject *> *,反之亦然,即使可以将NSString *分配给NSObject *。 (另一方面,NSArray的类型参数是协变的(它声明为NSArray<__covariant ObjectType>),这意味着NSArray<NSString *> * 可以分配给{{1} }。

NSArray<NSObject *> *甚至无法分配给NSMutableArray<NSString *> *,反之亦然,即使NSMutableArray<id> *可以分配给NSString *并且id可以分配给{ {1}},双向。我想这是因为id关闭了静态类型检查,但仅在使用实际类型NSString *时才关闭,而对于以id作为类型参数的类型则不这样做。

idid的“有限”版本-它关闭了静态类型检查,但仅当分配给__kindof superclass *的子类型或从id的子类型中分配时才关闭。出于同样的原因,无法将superclass *分配给以上NSMutableArray<id> *,也不能将NSMutableArray<someclass *> *分配给NSMutableArray<__kindof superclass *> *

答案 1 :(得分:-1)

您具有继承 A-> B (其中 A 是子类,而 B 是超类),则声明了一个容器保留 A 的实例,但是您试图将 B 的实例放入容器中。不能保证 B 的所有实例也都是 A 的实例。

想象一下还有另一个类 C-> B (其中 C B B 与上述相同的超类)。在这种情况下, C __ kindof B ,但不是 __ kindof A ,因此警告。

长话短说:声明容器时,您需要使用 __ kindof超类,以禁止显示警告。