删除Xcode"不兼容的类型"为包含子类的子类属性键入警告

时间:2017-09-01 21:27:03

标签: objective-c xcode subclass compiler-warnings suppress-warnings

A类定义属性" items"作为包含类X实例的有序集。

B类子类A,并重新定义"项目" property作为包含类Y的实例的有序集,X的子类。

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

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

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

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

我实际上做错了什么或者这是一个Xcode错误?如何删除此警告?

1 个答案:

答案 0 :(得分:1)

你不能说这是一个错误,因为讨论这个子类中的参数的子类是正确还是错误是讨论的主题。应用Liskov's substitution principle必须可以在集合中添加X项,因为基类允许这样做。如果子类禁止它,那么它就违反了原则。

但是,您应该记住,Swift引入了集合的“输入”,并且有动力为Swift编译器提供更多类型信息。它喜欢这样。

它类似于纯粹的Objective-C中的反概念。如果您不想使用Swift中的类,请简单省略它。

给你一个更简单的例子。具有:

@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的实例,但它的集合中有一个与约束不匹配的成员。