objective-c – 为什么编译器在子类中重新声明基类的readwrite属性为readonly时会发出警告?

后来引用的Apple文档似乎表明这是允许的,尽管我承认从来没有理由在子类中直到现在才这样做.

我有一个带有公共readwrite属性的基类和一个子类,我将该属性重新声明为readonly.子类还有一个类扩展,它再次将该属性重新声明为readwrite,以实现常见的“public readonly,private readwrite”Objective-C模式.但是,我得到以下编译器警告:

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

我在10.7上使用带有LLVM 2.1的Xcode 4.1 build 4B110(尽管LLVM GCC4.2和GCC4.2给出了相同的警告).

这是一个展示编译器警告的精简示例:

#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

这是Apple The Objective-C Programming Language的相关段落:

Property Redeclaration

You can redeclare a property in a subclass,but (with the exception of
readonly versus readwrite) you must repeat its attributes in whole in
the subclasses. The same holds true for a property declared in a
category or protocol—while the property may be redeclared in a category
or protocol,the property’s attributes must be repeated in whole.

If you declare a property in one class as readonly,you can redeclare it
as readwrite in a class extension (see “Extensions”),in a protocol,or
in a subclass (see “Subclassing with Properties”). In the case of a class
extension redeclaration,the fact that the property was redeclared prior
to any @synthesize statement causes the setter to be synthesized. The
ability to redeclare a read-only property as read/write enables two
common implementation patterns: a mutable subclass of an immutable class
(Nsstring,NSArray,and NSDictionary are all examples) and a property that
has a public API that is readonly but a private readwrite implementation
internal to the class. The following example shows using a class extension
to provide a property that is declared as read-only in the public header
but is redeclared privately as read/write.

我一直在类扩展中重新声明公共readonly属性readwrite,但我想我从来没有理由做一个子类.但是,除非我读错了,否则上面的段落似乎表明它是犹太人.任何人都可以让我直接和/或调和文档和编译器之间的明显冲突吗?

我为什么要这样做?当然,我的现实情况更复杂.如果需要的话,我可以进行设计更改以解决这个问题,但这似乎是最不摩擦的替代方案(完全需要这样做是由其他变化驱动).

解决方法

它表示你可以将readonly属性重新声明为readwrite但是你正在做相反的事情.你不能/不应该这样做,因为它可以这样做:
Sub* s = [[[Sub alloc] init] autorelease];
Base* b = s; 
b.foo = YES; //legal for `Base` objects,but not legal for `Sub` objects

这违反了the Liskov Substitution Priciple.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...