I have a class called AbstractBook, which has a property:
@property(strong) AbstractPage *page;
Now say I have a subclass of AbstractBook called WhiteBook and a subclass of AbstractPage called WhitePage. I want the WhiteBook class to inherit the page object, but in this class, I want it to be the specific WhitePage class instead of AbstractPage.
So, in WhiteBook, I just redeclared the property as WhitePage:
@property(strong) WhitePage *page;
However, I am getting a warning: WhitePage is incompatible with AbstractPage inherited from AbstractBook. What is the right way to implement what I’m going for?
What you want to do is fundamentally impossible. Don’t forget that this:
declares a getter and a setter.
Generally speaking (this is for OO programming generally, not just Objective-C), there is no problem with an override getter returning a subclass of the return type of the super class implementation because this does not break the API contract. In your case, an instance of
WhitePageis also anAbstractPage.However, the setter is different. You can’t restrict the type of the parameter because your subclass must be useable anywhere where an
AbstractBookis used, so code that invokes the setter on something that it thinks is anAbstractBookis entitled to pass in an instance of anyAbstractPagesubclass, because that is what the API says.I think what I would do is add a method to
AbstractBookcalled something likethat returns true always in the base class but true only for white pages in
WhiteBook. Then I would manually implement the setter as follows:Document that the setter will throw an exception if the page is not legal and that people should use the
isLegalPage:method to test this.The alternative id to have a read only property and use different setters in the base class and subclass, or don’t have a setter at all in the base class.