删除包含子类的子类属性的 Xcode "incompatible type" 类型警告

Remove Xcode "incompatible type" type warning for subclassed properties containing subclasses

Class A 将 属性 "items" 定义为包含 class X.

实例的有序集

Class B subclasses A,并将 "items" 属性 重新定义为包含 class Y 实例的有序集,子class 的 X.

// Defined in class A
@property NSOrderedSet<__kindof X *> *items;

// Defined in class B
@property NSOrderedSet<__kindof Y *> *items;

所有 Y 都是 X 的一种,因此子 classed 属性 应该有效,但是 Xcode 在 class B 中生成以下警告:

Property type 'NSOrderedSet<__kindof Y *> *' is incompatible with type 'NSOrderedSet<__kindof X *> *' inherited from 'A'

我真的做错了什么还是 Xcode 错误?我怎样才能删除这个警告?

你不能说这是一个错误,因为它是一个讨论的主题,在一个 subclass 中这样的参数 subclassing 是正确的还是错误的。应用 Liskov's substitution principle 必须可以将 X 的项目添加到集合中,因为基础 class 允许 this.Then 这是违反原则的,如果 sub class禁止。

但是,您应该记住 "typing" 集合是在 Swift 中引入的,目的是为 Swift 编译器提供更多类型信息。喜欢。

纯粹是反概念Objective-C。如果您不想使用 Swift.

中的 class,只需省略它

给大家举个更简单的例子。拥有:

@interface BaseValue : NSObject
…
@end

@interface Subvalue : BasValue
- (void)anotherMethod;
…
@end

@interface BaseHolder : NSObject
@property NSMutableSet<BaseValue*>* values;
@end

@interface Subholder : BaseHolder 
@property NSMutableSet<Subvalue*>* values;
@end

在此示例中,集合的成员被限制为 Subvalue 的实例。因此 Subholder 内的代码——以及任何明确处理 Subholder 实例的代码都可以预期,集合内的项目可以使用选择器 anotherMethod 接收消息。

但是如果你这样做

BaseValue *baseValue = [BaseValue new];
BaseHolder *baseHolder = [Subholder new]; // Get an instance of *Subholder*. The assignment is allowed by Liskov … As long as Subholder introduces no additional constraints.
[baseHolder.values addObject:baseValue]; // From the compiler's point of view legal, because you said nothing about a subclass

这会中断,因为在运行时它是 Subholder 的一个实例,但它的集合中有一个与约束不匹配的成员。