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错误?如何删除此警告?
答案 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
的实例,但它的集合中有一个与约束不匹配的成员。