Class A defines the property "items" as an ordered set containing instances of class X.
Class B subclasses A, and redefines the "items" property as an ordered set containing instances of class Y, a subclass of X.
// Defined in class A
@property NSOrderedSet<__kindof X *> *items;
// Defined in class B
@property NSOrderedSet<__kindof Y *> *items;
All Y's are a kind of X's so the subclassed property should be valid, however Xcode generates the following warning within class B:
Property type 'NSOrderedSet<__kindof Y *> *' is incompatible with type 'NSOrderedSet<__kindof X *> *' inherited from 'A'
Am I actually doing something wrong or is this an Xcode bug? How can I remove this warning?
You cannot say that this is a bug, because it is a subject of discussions whether such a subclassing of parameters in a subclass is correct or wrong. Applying Liskov's substitution principle it has to be possible to add an item of
X
to the set, because the base class allows this.Then it is an infringement of the principle, if the subclass forbids it.However, you should remember that the "typing" of collections was introduced with Swift and was motivated to give the Swift compiler more type information. It likes that.
It is akin of anti-conceptual in pure Objective-C. Simply omit it, if you do not want to use the class from Swift.
To give you an example that is more simple. Having:
In this example, the members of the set are restricted to be instances of
Subvalue
. Therefore the code insideSubholder
– and any code explicitly dealing with instances ofSubholder
can expect, that the items inside the set can receive a message with the selectoranotherMethod
.But if you do this
This breaks, because at runtime it is an instance of
Subholder
, but it has a member in its collection that does not match the constraint.