稍後引用的Apple文檔似乎表明這是允許的,儘管我承認直到現在還沒有理由在子類中執行此操作。爲什麼在將子類的readwrite屬性重新聲明爲只讀時,編譯器會發出警告?
我有一個公共讀寫屬性和一個子類,我重新聲明屬性爲只讀的基類。該子類還有一個類擴展,它再次將屬性重新聲明爲readwrite,以實現常見的「public readonly,private readwrite」Objective-C模式。不過,我得到以下編譯器警告:
warning: Semantic Issue: Attribute 'readonly' of property 'foo' restricts attribute 'readwrite' of property inherited from 'Base'
我使用的Xcode 4.1構建4B110與LLVM 2.1(雖然LLVM GCC4.2和GCC4.2提供相同的警告信息)10.7。
這裏是一個精簡的例子展示了編譯器警告:
#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
下面是來自蘋果的The Objective-C Programming Language相關通道:
屬性重複
您可以在重新聲明屬性子類,但(除了 只讀與讀寫之外),您必須在 之後重複其整體屬性他的子類。 類別或協議中聲明的屬性也是如此 - 雖然該屬性可能在類別 或協議中重新聲明,但必須重複整個屬性的屬性。
如果您爲只讀聲明一個類的屬性,你可以在子類中重新聲明它 作爲一個類擴展讀寫(見「擴展」),在協議或 (參見「子類與屬性」) 。對於類別 擴展重新聲明,事實上該屬性在 之前重新聲明爲任何@synthesize語句會導致合成器被合成。 將只讀屬性重新聲明爲讀/寫的能力啓用了兩個公共實現模式:不可變類 (NSString,NSArray和NSDictionary都是示例)的可變子類以及 具有公共API的屬性是隻讀的,但是類內部的私有讀寫實現 。以下示例顯示使用類擴展 提供在公共標題 中聲明爲只讀的屬性,但被私下重新聲明爲讀/寫。
我重新聲明公共readonly屬性readwrite在類擴展中,但我想我從來沒有理由做它的子類。但是,除非我讀錯了,否則上面的段落似乎表明它是猶太教。任何人都可以讓我直接和/或協調文檔和編譯器之間的明顯衝突嗎?
爲什麼我要這樣做?當然,我的現實世界更加複雜。如果需要,我可以進行設計更改以解決此問題,但這似乎是最少摩擦的替代方案(完全需要這樣做是由其他更改引發的)。
湯姆說了些什麼。當超類提供公開的讀寫時,只讀取子類是沒有意義的。通常,您可以添加沿類層次結構的可變性(請參閱OS中提供的各種不可變 - >可變類集羣示例)。 – bbum
謝謝湯姆和寶貝。我(應該)更好地瞭解。我想我這個週末花了太多時間來思考我的實際問題,忽視了最初的原則。我甚至有第二次抓住自己的機會,但是我的大腦通過多次閱讀以某種方式在文檔第二段中「或者在一個子類中」被過濾出來。晚餐休息後,回到你的答案,我覺得這個有點傻。感謝一些清晰的,我喜歡Liskov鏈接! – Slipknot