2011-08-22 10 views
6

Il documento Apple citato in seguito sembra indicare che ciò è ammissibile, anche se ammetterò che non ho mai avuto motivo di farlo in una sottoclasse fino ad ora.Perché il compilatore avvisa quando si redeca la proprietà readwrite della classe base come readonly nella sottoclasse?

Ho una classe base con una proprietà di readwrite pubblica e una sottoclasse in cui redeclare la proprietà come readonly. La sottoclasse ha anche un'estensione di classe che ridichiara nuovamente la proprietà come readwrite per ottenere il comune pattern pubblico "read-readly, private readwrite" Objective-C. Tuttavia, ottengo il seguente avviso del compilatore:

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

sto usando Xcode 4.1 Build 4B110 con LLVM 2.1 (anche se LLVM GCC4.2 e GCC4.2 danno lo stesso avvertimento) su 10,7.

Ecco un esempio stripped-down che espone l'avviso del compilatore:

#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 

Ecco un passaggio rilevante dal The Objective-C Programming Language di Apple:

Proprietà ridichiarazione

È possibile ridichiarare un immobile in un sottoclasse, ma (ad eccezione di in sola lettura rispetto a readwrite) è necessario ripetere i suoi attributi per intero in t lui sottoclasse. Lo stesso vale per una proprietà dichiarata in una categoria o protocollo , mentre la proprietà può essere dichiarata in una categoria o un protocollo, gli attributi della proprietà devono essere ripetuti per intero.

Se si dichiara una proprietà in una classe come di sola lettura, è possibile ridichiarare che come readwrite in un'estensione di classe (vedi “Estensioni”), in un protocollo, o in una sottoclasse (vedi “Subclassing con Proprietà”) . Nel caso di una redazione dell'estensione della classe , il fatto che la proprietà sia stata dichiarata prima di a qualsiasi istruzione @synthesize fa sì che il setter sia sintetizzato. La capacità di redeclare una proprietà di sola lettura come lettura/scrittura abilita due modelli di implementazione comuni : una sottoclasse mutabile di una classe immutabile (NSString, NSArray e NSDictionary sono tutti esempi) e una proprietà che ha un'API pubblica che è di sola lettura, ma un'implementazione di readwrite privata interna alla classe. L'esempio seguente mostra l'utilizzo di un'estensione di classe per fornire una proprietà dichiarata di sola lettura nell'intestazione pubblica , ma viene dichiarata in privato come lettura/scrittura.

I redeclare public readonly proprietà readwrite in estensioni di classe per tutto il tempo, ma suppongo che non ho mai avuto motivo di farlo una sottoclasse. Tuttavia, a meno che non stia leggendo male, i paragrafi precedenti sembrano indicare che è kosher. Qualcuno può mettermi dritto e/o conciliare l'apparente conflitto tra i documenti e il compilatore?

Perché voglio farlo? La mia situazione del mondo reale è più complessa, ovviamente. Posso apportare modifiche al design per aggirare questo problema, se necessario, ma questa sembrava l'alternativa meno attrattiva (la necessità di fare tutto ciò è guidata da altri cambiamenti).

risposta

10

Si dice che è possibile ridichiarare una proprietà readonly come readwrite ma si sta facendo l'opposto.Non si può/non si deve fare perché è possibile farlo:

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

E 'una violazione della the Liskov Substitution Priciple.

+0

Quello che Tom ha detto. Non ha senso creare una sottoclasse di sola lettura quando la superclasse offre la possibilità di readwrite pubblicamente. Generalmente, si aggiunge la mutabilità andando giù nella gerarchia delle classi (vedere i vari esempi di cluster Immutable -> Mutable class forniti nel sistema operativo). – bbum

+0

Grazie Tom e bbum. Io (dovrei) sapere meglio. Penso di aver passato troppo tempo questo fine settimana a rimuginare sul mio problema reale ea perdere di vista i primi principi. Avevo anche una seconda possibilità di catturarmi, ma il mio cervello in qualche modo filtrato "o in una sottoclasse" nel secondo paragrafo del documento attraverso letture multiple. Dopo una pausa per la cena e tornando alle tue risposte, mi sento un po 'stupido riguardo a questo. Grazie per la chiarezza, e mi è piaciuto il collegamento Liskov! – Slipknot

Problemi correlati