Obejście w celu uzyskania chronionych właściwości w Objective-C
Próbowałem znaleźć obejście, aby zadeklarować @protected properties w Objective-C, aby tylko podklasy w hierarchii miały do nich dostęp (tylko do odczytu, nie do zapisu). Czytałem, że nie ma udokumentowanego sposobu na zrobienie tego, więc pomyślałem o tym obejściu i chciałem zapytać o opinię StackOverflow na ten temat.
Każda klasa niestandardowa na szczycie hierarchii zawiera trzy klasy, jedną implementację i dwa interfejsy. Nazwijmy je:
ClassA.h
ClassA_protected.h
ClassA.m
Wtedy każda podklasa tej klasy byłoby jak zwykle:
ClassB.h
ClassB.m
Najpierw stworzyłem interfejs ClassA.h gdzie deklaruję chronioną zmienną int, więc każda podklasa ClassA może mieć do niej dostęp:
@interface ClassA : NSObject{
@protected
int _myProtectedInt;
}
@end
Następnym krokiem jest obejście, o którym mówiłem. Jednak po przeczytaniu zobaczysz, że jest całkiem prosto. Zadeklarowałem drugi interfejs o nazwie ClassA_protected.h , które faktycznie działa jako rozszerzenie klasy.h i pozwala nam oznaczyć nieruchomość jako readonly
:
#import "ClassA.h"
@interface ClassA ()
@property (nonatomic , readonly) int myProtectedInt;
@end
Ostatnim etapem przygotowania chronionej hierarchii jest zadeklarowanie jej implementacji w ClassA.M gdzie tylko syntetyzujemy naszą własność:
#import "ClassA_protected.h"
@implementation ClassA
@synthesize myProtectedInt = _ myProtectedInt;
@end
W ten sposób każda klasa, która musi być podklasą ClassA.h, zaimportuje ClassA_protected.h zamiast tego. Więc dziecko jak, na przykład ClassB.h , będzie następujące:
#import "ClassA_protected.h"
@interface ClassB : ClassA
@end
I przykład dostępu do tej właściwości z ClassB.m ' s realizacja:
@implementation ClassB
-(void) method {
//edit protected variable
_myProtectedInt= 1;
//normal access
self.muProtectedInt;
}
@end
4 answers
Jasne, to działa dobrze. Apple używa tego samego podejścia na przykład w klasie UIGestureRecognizer
. Podklasy muszą zaimportować dodatkowy plik UIGestureRecognizerSubclass.h
i nadpisać metody zadeklarowane w tym pliku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-15 09:05:59
Dla prostych "właściwości" wystarczy użyć ivar zamiast. To jest tak dobre, jak właściwości dla wszystkich praktycznych celów.
Ponadto domyślna wartość jest już chroniona.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-10 08:00:26
Jeśli pytasz o opinię, to jest moja: jeśli ktoś zdecyduje się mutować
_myProtectedInt
I tak pewnie mu się uda, bo z Runtime Objective-C jest to na pewno możliwe. Poza tym, Twoje rozwiązanie jest całkiem OK.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-15 09:12:12
Importuj chroniony nagłówek tylko w implementacji. np.
ClassB.h
#import "ClassA.h"
@interface ClassB : ClassA
@end
ClassB.m
#import "ClassA_protected.h"
@implementation ClassB
@end
A w frameworku chroniony nagłówek powinien być oznaczony jako project, więc nie jest zawarty w publicznych nagłówkach frameworku. Apple zwykle używa przyrostka _Internal.h dla ich chronionych metod.
Dla init lub nadpisywania leniwej loaded get property będziesz potrzebował bezpośredniego dostępu do @ proteced ivar, jednak dla Twojego użytku lepiej byłoby ponownie zgłosić właściwość jako readwrite zamiast tego możesz skorzystać z dowolnych funkcji settera, na przykład atomicity.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-08 10:30:06