2011-08-22 17 views
6

Apple'ın daha sonra aktardığı alıntı, bunun mümkün olduğuna işaret ediyor gibi görünse de, şu ana kadar bir alt sınıfa bunu yapmak için hiçbir zaman bir neden olmayacağımı kabul edeceğim.Neden derleyici, alt sınıfın readwly özelliği olarak alt sınıfın readwrite özelliğini yeniden sınıflandırırken uyarır?

Genel readwrite özelliğine sahip bir temel sınıfım var ve özelliği okuduğum bir alt sınıf var. Alt sınıf ayrıca, ortak “public readonly, private readwrite” Objective-C modelini elde etmek için özelliği readwrite olarak yeniden sınıflandıran bir sınıf uzantısına da sahiptir. Ancak, aşağıdaki derleyici uyarı alıyorum:

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

Ben LLVM 2.1 ile Xcode 4.1 build 4B110 kullanıyorum 10.7 üzerinde (LLVM GCC4.2 ve GCC4.2 aynı uyarı vermek rağmen).

#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 

İşte Apple'ın The Objective-C Programming Language alakalı bir pasaj var: Burada

derleyici uyarı sergileyen sadeleştirilmiş örnek

Mülkiyet yeniden bildirilmiş

Bir bir özellik redeclare olabilir

alt sınıfı, ancak ( readonly versus versus versus ile hariç) t o alt sınıflar. Aynı özellik, kategorisinde veya protokolde bildirilen bir özellik için de geçerlidir - özellik, kategorisinde veya protokolde yeniden bildirilmiş olabilir. Mülkün özelliklerinin tamamı tekrarlanmalıdır. Eğer salt okunur olarak bir sınıfta bir mal beyanında ise

, siz (“Özellikler ile Subclassing” bölümüne bakınız) bir alt sınıfta bir protokolde, (“Extensions” bölümüne bakınız), bir sınıf uzantısında ReadWrite olarak o redeclare, veya . Bir sınıfın uzantısı yeniden sınıflandırması durumunda, özelliğin öncesinde herhangi bir @synthesize ifadesine yeniden bildirilmesi, ayarlayıcının sentezlenmesine neden olur. , salt okunur bir özelliği okuma/yazma olarak yeniden tanımlama yeteneğini sağlar: iki ortak uygulama desenleri: (NSString, NSArray ve NSDictionary öğesinin değişmez bir sınıfının bir değişken alt sınıfı) ve 'un bir genel API'ye sahip olduğu bir özellik readonly ancak sınıfa içten bir özel readwrite uygulaması . Aşağıdaki örnek, sınıf uzantısının genel başlığında salt okunur olarak bildirilen ancak özel olarak okuma/yazma olarak yeniden bildirilen bir özellik sağlamak için kullanıldığını gösterir.

Genel yayın okuma özelliklerini sınıf uzantılarında her zaman yeniden yazarım, ama sanırım bunu bir alt sınıfta yapmak için hiçbir nedenim olmadı. Bununla birlikte, yanlış okuyamıyorsam, yukarıdaki paragraflar bunun koşucu olduğunu gösteriyor. Herkes beni doğrudan ve/veya dokümanlar ile derleyici arasındaki anlaşmazlığı uzlaştırdı mı?

Bunu neden yapmak istiyorum? Benim gerçek dünya durumum elbette daha karmaşık. Gerektiğinde, bu konuda çalışmak için tasarım değişiklikleri yapabilirim, fakat bu en az sürtünmeli alternatif gibi görünüyordu (bunu yapmak için gereken her şey diğer değişimler tarafından yönlendiriliyor).

cevap

10

Bir readonly özelliğini readwrite olarak yeniden bildirebileceğinizi ancak bunun tersini yaptığınızı söylüyor.Bunu yapmak mümkün çünkü/bunu yapmak gerekir olamaz:

Sub* s = [[[Sub alloc] init] autorelease]; 
Base* b = s; 
b.foo = YES; //legal for `Base` objects, but not legal for `Sub` objects 

O the Liskov Substitution Priciple ihlali anlamına gelir.

+0

Tom ne dedi. Üst sınıf teklifleri herkese açık olarak okunduğunda bir alt sınıfı okumak için mantıklı değildir. Genel olarak, sınıf hiyerarşisine inen mutabiliteyi eklersiniz (OS'de sağlanan çeşitli Immutable -> Mutable sınıfı küme örneklerine bakın). – bbum

+0

Teşekkürler Tom ve bbum. Daha iyi bilmeliyim. Bu haftasonu benim asıl sorunumun üstesinden gelmek için uzun zaman harcadım ve ilk prensipleri gözden kaçırdım. Kendimi yakalamak için ikinci bir şansım bile vardı, ama beynim bir şekilde çoktan okunan bir okuma ile dokümanın ikinci paragrafında "bir alt sınıfta" filtrelendi. Bir yemek molası verdikten ve cevaplarınıza geri döndükten sonra, bu konuda biraz aptalca hissediyorum. Biraz açıklık için teşekkürler ve Liskov bağlantısının tadını çıkardım! – Slipknot

İlgili konular