【发布时间】:2011-10-31 19:49:57
【问题描述】:
稍后引用的 Apple 文档似乎表明这是允许的,尽管我承认直到现在我才没有理由在子类中这样做。
我有一个带有公共读写属性的基类和一个我将属性重新声明为只读的子类。子类还有一个类扩展,它再次将属性重新声明为读写,以实现常见的“公共只读,私有读写”Objective-C 模式。但是,我收到以下编译器警告:
warning: Semantic Issue: Attribute 'readonly' of property 'foo' restricts attribute 'readwrite' of property inherited from 'Base'
我在 10.7 上使用 Xcode 4.1 build 4B110 和 LLVM 2.1(尽管 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 的相关段落:
财产再申报
你可以在子类中重新声明一个属性,但是(除了 readonly 与 readwrite )你必须在整个重复它的属性 子类。对于在 a 中声明的属性也是如此 类别或协议——而属性可以在类别中重新声明 或协议,属性的属性必须全部重复。
如果你在一个类中声明一个属性为只读,你可以重新声明它 作为类扩展(参见“扩展”)、协议中的读写,或 在子类中(请参阅“使用属性进行子类化”)。在班级的情况下 扩展重新声明,该属性之前重新声明的事实 任何@synthesize 语句都会导致setter 被合成。这 将只读属性重新声明为读/写的能力使两个 常见的实现模式:不可变类的可变子类 (NSString、NSArray 和 NSDictionary 都是示例)和一个属性 有一个只读的公共 API,但有一个私有的读写实现 类的内部。以下示例显示使用类扩展 提供在公共标头中声明为只读的属性 但被私下重新声明为读/写。
我一直在类扩展中重新声明公共只读属性 readwrite,但我想我从来没有理由将它作为一个子类。但是,除非我读错了,否则上面的段落似乎表明它是洁净的。谁能让我直截了当和/或调和文档和编译器之间的明显冲突?
我为什么要这样做?当然,我的实际情况要复杂得多。如果需要,我可以进行设计更改以解决此问题,但这似乎是摩擦最小的替代方案(这样做的需要是由其他更改驱动的)。
【问题讨论】: