Why does the compiler warn about updating the readwrite property of the base class as readonly in a subclass?

The Apple quote quoted later seems to indicate that this is acceptable, although I admit that I have no reason to do so in the subclass so far.

I have a base class with the public readwrite property and a subclass where I override the property as readonly. The subclass also has a class extension that again overrides the property as readwrite to achieve the Objective-C general template "public readonly, private readwrite". However, I get the following compiler warning:

warning: Semantic Issue: Attribute 'readonly' of property 'foo' restricts attribute 'readwrite' of property inherited from 'Base' 

I am using Xcode 4.1 build 4B110 with LLVM 2.1 (although LLVM GCC4.2 and GCC4.2 give the same warning) on ​​10.7.

Here is an example that shows a compiler warning:

 #import <Foundation/Foundation.h> @interface Base : NSObject @property (nonatomic, readwrite) BOOL foo; @end @implementation Base @dynamic foo; @end // Subclass @interface Sub : Base @property (nonatomic, readonly) BOOL foo; @end // Class extension @interface Sub () @property (nonatomic, readwrite) BOOL foo; @end @implementation Sub @dynamic foo; // it warns with @synthesize as well @end 

Here is an excerpt from Apple Objective-C Programming Language :

Reservation of properties

You can override a property in a subclass, but (with the exception of readonly versus readwrite), you must completely repeat your attributes in subclasses. The same is true for a property declared in a category or protocol - while a property can be redesigned into a category or protocol, the attributes of the properties must be repeated in their entirety.

If you declare a property in one class as read-only, you can update it as readwrite in the class extension (see "Extensions"), in the protocol, or in a subclass (see "Subclassing using properties"). In the case of a class, a renewal notice, the fact that the property has been re-indicated earlier to any @synthesize statement causes the synthesizer to be synthesized. the ability to override a read-only property because read / write allows you to use two common implementation patterns: a mutable subclass of an immutable class (NSString, NSArray and NSDictionary - all examples) and a property that has a public API that is read-only, but a private readwrite implementation inside class. The following example uses a class extension to provide a property that is declared read-only in a public header but closes privately, like read / write.

I am constantly updating the readonly readwrite public properties in class extensions, but I think I never had a reason to make it a subclass. However, if I do not read it incorrectly, the above paragraphs indicate that they are kosher. Can someone set me straight and / or reconcile the apparent conflict between the documents and the compiler?

Why do I want to do this? Of course, my real situation is more complicated. I can make design changes to get around this if necessary, but it seemed like an alternative to less friction (the need for it generally depends on other changes).

+6
source share
1 answer

It says that you can override the readonly property as readwrite , but you do the opposite. You cannot / should not do this because it can be done:

 Sub* s = [[[Sub alloc] init] autorelease]; Base* b = s; b.foo = YES; //legal for `Base` objects, but not legal for `Sub` objects 

This is a violation of the Liskov Note Assignment .

+10
source

Source: https://habr.com/ru/post/895553/


All Articles