代码之家  ›  专栏  ›  技术社区  ›  ATLief

删除包含子类的子类属性的Xcode“Compatible type”类型警告

  •  1
  • ATLief  · 技术社区  · 7 年前

    类B是A的子类,并将“items”属性重新定义为包含类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 回复  |  直到 7 年前
        1
  •  1
  •   Amin Negm-Awad    7 年前

    你不能说这是一个bug,因为在一个子类中这样的参数子类化是正确的还是错误的,这是一个讨论的主题。应用 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 子文件夹 可以预期,集合中的项目可以通过选择器接收消息 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
    

    这会中断,因为在运行时它是 子文件夹