Обобщение: несовместимые типы указателей, инициализирующие NSMutableArray* с выражением типа 'NSMutableArray <__ kindof суперкласс *> * - PullRequest
0 голосов
/ 27 августа 2018

У меня есть это свойство:

@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.

Ответы [ 2 ]

0 голосов
/ 14 сентября 2018

Общий параметр NSMutableArray является инвариантным (он объявлен @interface NSMutableArray<ObjectType>, а не @interface NSMutableArray<__covariant ObjectType> или @interface NSMutableArray<__contravariant ObjectType>).Это означает, что аргумент типа должен точно совпадать, чтобы он был совместимым.

Это означает, что NSMutableArray<NSString *> * нельзя присвоить NSMutableArray<NSObject *> * или наоборот, даже если NSString * можно присвоить NSObject *.(С другой стороны, параметр типа NSArray является ковариантным (он объявлен NSArray<__covariant ObjectType>), что означает, что NSArray<NSString *> * можно присвоить NSArray<NSObject *> *.)

NSMutableArray<NSString *> * нельзя даже назначить на NSMutableArray<id> * или наоборот, даже если NSString * можно назначить на id, а id можно назначить на NSString * в обоих направлениях.Я предполагаю, что идея состоит в том, что id отключает статическую проверку типов, но только при использовании фактического типа id, а не для типов, которые имеют id в качестве аргумента типа.

__kindof superclass *является разновидностью «ограниченной» версии id - она ​​отключает статическую проверку типов, но только при назначении и из подтипов superclass *.По той же причине, по которой NSMutableArray<id> * нельзя присвоить или из NSMutableArray<someclass *> * выше, NSMutableArray<__kindof superclass *> * также нельзя присвоить или из NSMutableArray<subclass *> *.

0 голосов
/ 27 августа 2018

У вас есть наследство A -> B (где A - это подкласс, а B - это суперкласс), вы объявили контейнер для хранения экземпляров A но вы пытаетесь поместить экземпляры B внутрь контейнера. Не гарантируется, что все экземпляры B также являются экземплярами A .

Представьте, что у вас есть другой класс C -> B (где C - это подкласс B , а B - то же самое суперкласс, упомянутый выше). В этом случае C - это __ kindof B , но это не __ kindof A , отсюда и предупреждение.

Короче говоря: вам нужно использовать __ kindof суперкласс при объявлении вашего контейнера, чтобы подавить предупреждение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...