后来引用的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的相关段落:
财产重新申报
您可以重新声明子类中的属性,但(除了 readonly与readwrite)你必须重复其属性 子类。对于在a中声明的属性也是如此 类别或协议 - 而财产可以在一个类别中重新申报 或协议,属性的属性必须重复。
如果您将一个类中的属性声明为readonly,则可以重新声明它 作为类扩展中的读写(请参阅“扩展”),在协议中,或 在子类中(请参阅“使用属性进行子类化”)。在班级的情况下 延期重新申报,事先已重新申报该财产 任何@synthesize语句都会导致setter被合成。该 能够重新声明只读属性作为读/写启用两个 常见的实现模式:不可变类的可变子类 (NSString,NSArray和NSDictionary都是示例)和一个属性 有一个只读的公共API,但是私有的readwrite实现 课堂内部。以下示例显示了使用类扩展 提供在公共标头中声明为只读的属性 但是在读/写时被私下重新声明。
我一直在类扩展中重新声明public readonly属性readwrite,但我想我从来没有理由这样做一个子类。但是,除非我读错了,否则上面的段落似乎表明它是犹太人。任何人都可以让我直接和/或调和文档和编译器之间的明显冲突吗?
为什么我要这样做?当然,我的现实情况更复杂。如果需要的话,我可以进行设计更改以解决此问题,但这似乎是摩擦力最小的替代方案(完全需要这样做是由其他更改驱动)。
答案 0 :(得分:12)
它表示您可以将readonly
属性重新声明为readwrite
但您正在执行相反的操作。你不能/不应该这样做,因为它可以这样做:
Sub* s = [[[Sub alloc] init] autorelease];
Base* b = s;
b.foo = YES; //legal for `Base` objects, but not legal for `Sub` objects