Quando si sottoclama una classe Apple che elenca ivars privati nel file .h, è corretto redeclare questi ivar nella propria sottoclasse nell'estensione di classe @interface all'interno del file .m della sottoclasse per renderli accessibili all'implementazione della sottoclasse. ?È corretto dichiarare ivars privati in una sottoclasse per renderli accessibili?
risposta
È necessario tenere a mente che dichiarare una variabile di istanza in una sottoclasse non ridichiarare una variabile di istanza superclasse esistente con lo stesso nome, indipendentemente dal ridichiarazione presunto essendo nell'interfaccia pubblico o un'estensione di classe. Anche se usi lo stesso nome, è una variabile di istanza diversa.
Puoi provarlo tu stesso. Ad esempio:
@interface Base : NSObject {
@private
int _number;
}
@end
@implementation Base
- (id)init { self = [super init]; if (self) _number = 10; return self; }
- (void)logNumber { printf("base = %d\n", _number); }
@end
@interface Derived : Base
@end
@interface Derived() {
int _number;
}
@end
@implementation Derived
- (id)init { self = [super init]; if (self) _number = 20; return self; }
- (void)logNumberDerived { printf("derived = %d\n", _number); }
@end
int main(void) {
Derived *o = [Derived new];
[o logNumber];
[o logNumberDerived];
return 0;
}
uscite:
base = 10
derived = 20
perché _number
in superclasse è diverso da _number
in sottoclasse (estensione). Se si controlla i simboli in uscita binaria con nm -a
, si noterà che il compilatore genera due simboli diversi:
s _OBJC_IVAR_$_Base._number
s _OBJC_IVAR_$_Derived._number
ho trovato qui la risposta che corrisponde esattamente la mia: http://lists.apple.com/archives/cocoa-dev/2007/Feb/msg00939.html
Se l'hanno fatta @private e non @protected si dovrebbe supporre che è per una ragione. Che la ragione potrebbe naturalmente essere semplicemente che è prudente rendere tutto @private finché non si sa una buona ragione per non ...
Detto questo, si potrebbe molto definitivamente non essere OK per accedervi direttamente , anche se è tecnicamente possibile.
La cosa sicura da fare è rifare tutto nella propria classe, mentre richiede al manutentore della superclasse di esporre la funzionalità necessaria nell'interfaccia pubblica/protetta.
Già. È un po 'vecchio e non molto ufficiale, ma un buon modo di pensare. – uchuugaka
Interessante. Ma presumibilmente, se sono altrimenti dichiarati uguali, il tuo esempio indica che quello indicato nei metodi implementati in super sarà quello dichiarato in super. Quello indicato nei metodi dichiarati in sottoclasse sarà quello dichiarato nella sottoclasse? – uchuugaka
@uchuugaka corretto. Dal momento che la superclasse ivar è privata, la sottoclasse non può accedere a quell'arena e vede solo il proprio, diverso ivar. È necessario fare uno sforzo extra (ad esempio, utilizzando l'API runtime Objective-C) per poter accedere alla superclasse ivar. –
verificato. Ho provato questo con diverse varianti, setter, getter e proprietà e sicuro come può essere è come dici tu. E questo comportamento potrebbe facilmente "sembrare" funzionare, quando un ivar è un oggetto la cui classe è una classe genitrice dell' ivar che "penso" sto redecando ... (sì è così che sono arrivato a questa domanda, ma usando un il tipo C ivar invalicabile è più chiaro!) – uchuugaka