2011-11-23 22 views
2

我有以下代碼:繼承一個不可變拷貝屬性作爲可變保留

@interface Room : NSObject 
{ 
@protected 
    NSMutableDictionary* mCustomProperties; 
} 

@property (readonly, copy) NSDictionary* CustomProperties; 

@end 



@interface MutableRoom : Room 
{ 
} 

@property (readwrite, retain) NSMutableDictionary* CustomProperties; 

@end 

這些屬性然後通過訪問mCustomProperties後來實現。 我知道,不允許重新聲明內存管理屬性或子類中屬性的數據類型與基類中的屬性不同。 但是,我想實現以下功能: - 只給只讀訪問不可變基類中的字典。由於成員是一個NSMutableDictionary,只是將它作爲NSDictionary的保留實例返回時,意味着它的簡單轉換會使其再次變爲可變的,甚至是無意的,當屬性的用戶將訪問變量作爲NSObject實例存儲在某個位置,然後恢復稍後回來的原始類型。因此,我想通過readonly屬性中的不可變副本返回可變字典。 - 對可變子類中的字典進行完全讀寫訪問。因爲你不僅應該能夠在那裏存儲另一個字典,而且要改變現有的字典的內容,我希望子類中的屬性不僅要被讀寫,而且要被保留,而不是被複制,所以原始值將被訪問,並以NSMutableDictionary的形式訪問,而不是作爲NSDictionary訪問,以便可以通過屬性添加,刪除或更改字典的條目。

有沒有比抑制警告或使用兩個不同名稱的屬性更優雅的方式?

回答

1

聲明一個可變/不可變的一對一類集羣時,我經常找到另一個它最簡單的繼承,而是利用一個內部類的實施方式中,像這樣:

// Room.h 
@interface Room : NSObject 
// ... 
@end 

@interface MutableRoom : Room 
// ... 
@end 

// MONRoom.h 
@class RoomImp; 

@interface MONRoom : Room 
{ 
@private 
    RoomImp * imp; 
} 

@property (readonly, copy) NSDictionary* CustomProperties; 

@end 

@interface MONMutableRoom : MutableRoom 
{ 
@private 
    RoomImp * imp; 
} 

@property (readwrite, retain) NSMutableDictionary* CustomProperties; 

@end 

// RoomImp.h 
@interface RoomImp : NSObject 
{ 
@private 
    NSMutableDictionary* mCustomProperties; 
} 

// ... 

@end 
+0

是的,當然實現看起來有點複雜,但這樣我實際上可以實現預期的接口:) – Kaiserludi

+0

好吧,想一想更多關於你的方法: 這樣我只能在MON上使用該屬性(-Mutable- )房間,不在(Mutable-)房間,我可以嗎?但是當然,我必須在所有接口中使用(Mutable-)Room,以便可以傳遞可變版本,其中不可變被指定爲參數類型。這意味着,人們不得不在所有需要訪問屬性的地方將所有(可變)房間實例拋棄到MON(可變)房間,否則將無法使用點對點語法。 所以看來,這不是一個真正合適的解決方案。 – Kaiserludi

+0

@Kaiserludi通常,它工作正常 - 你使用不可變/不可變變體來提供專門的複製語義 - 基本上,當使用'RoomImp'時提供公共方法和任何額外的語義。公開暴露可變成員也是有風險的。相反,你可能會在'setProperties:'或'setProperty:value:'的行中看到一些東西。 – justin