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
Author: Binarian, 2012-06-15

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.

 20
Author: Ole Begemann,
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.

 7
Author: Septiadi Agus,
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.

 3
Author: Oleg Trakhman,
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.

 0
Author: malhal,
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