Istnieje klasa, która wygląda tak (ja pominięciem importu dla zwięzłość):Zastępowanie właściwość tylko do odczytu w podklasie
Base.h:
@interface Base : NSObject
@property (strong, readonly) NSString *something;
- (id)initWithSomething:(NSString *)something;
@end
bazowej. m:
@implementation Base
- (id)initWithSomething:(NSString *)something {
self = [super init];
if (self) _something = something;
return self;
}
@end
Jak widać, 'coś' właściwość jest tylko do odczytu. Teraz chcę utworzyć podklasę, który zastępuje że nieruchomość będzie zapisu, a także:
Sub.h:
@interface Sub : Base
@property (strong) NSString *something;
@end
Sub.m:
@implementation Sub
@end
I kod:
main.c:
int main(int argc, const char * argv[]) {
@autoreleasepool {
Sub *o = [Sub new];
o.something = @"foo";
NSLog(@"%@", o.something);
}
return 0;
}
Ten kod jest następujący:
2013-09-07 13:58:36.970 ClilTest[3094:303] *** Terminating app due to uncaught
exception 'NSInvalidArgumentException', reason: '-[Sub setSomething:]: unrecognized
selector sent to instance 0x100109ff0'
Dlaczego tak jest? Dlaczego nie znajduje setSelector?
Kiedy to zrobić w podklasie Zamiast:
Sub.m:
@implementation Sub
@synthesize something = _something;
@end
to wszystko działa. Czy to oznacza, że własność podklasy nie jest domyślnie syntezowana, mimo że jest zdefiniowana jako @property
w ? Czy kompilacja w jakiś sposób "widzi" automatycznie wygenerowany getter z bazy i nie generuje ustawiającego? I dlaczego, myślę, że seter powinien zostać wygenerowany, ponieważ jeszcze nie istnieje. Używam Xcode 4.6.2, a projekt to narzędzie Cli (typ Foundation), ale to samo dzieje się w moim rzeczywistym projekcie, który jest aplikacją na iPhone'a.
Tło: Mam ciężki obiekt (instancja Base), który wymaga połączenia Bluetooth z niektórymi urządzeniami i mam stworzyć kontroler widoku dla niektórych funkcji. Dla łatwego testowania nie chcę być podłączony do BT (w rzeczywistości potrzebowałbym fizycznego urządzenia i przetestować kod na nim), chciałbym móc przetestować go w symulatorze. To, co wymyśliłem, polega na tym, że po prostu utworzę podklasę (Sub), która koduje kilka metod/właściwości i używa jej zamiast tego, a kiedy kod jest gotowy, po prostu usuwam kod dla podklasy, zastępuję jego instancję poprawnym , przetestuj urządzenie, zatwierdz i pchnij. Działa to naprawdę dobrze, z wyjątkiem tej dziwnej rzeczy z powyższym @property
.
Czy ktoś może mi powiedzieć, co się dzieje z przesłonięciem nieruchomości?
Oprócz działającego rozwiązania, chciałem dodać, że "zwiększenie" poziomu prywatności atrybutu jest sprzeczne z zasadami OOP. Zwykle (ale nie zawsze), jeśli musisz uczynić właściwość bardziej widoczną (prywatna -> chroniona, lub chroniona -> publiczna) w podklasie, to coś jest nie tak w modelu. Odwrotnie dzieje się z metodami. Jeśli klasa nadrzędna ma metodę A, nie powinieneś uczynić A bardziej prywatnym (public -> protected, lub protected -> private) w podklasie. –