I have class A
which has this declaration in it's .m
file:
@implementation A {
NSObject *trickyObject;
}
And class B
which has this declaration in it's .h
file:
@interface B : A
@end
Is there any possibility to access the trickyObject
from a method declared in the class B
?
If you have a property or method that is private, but you want to make accessible to subclasses, you can put the declaration in a category .
So consider A
:
// A.h
@import Foundation;
@interface A : NSObject
// no properties exposed
@end
And
// A.m
#import "A.h"
// private extension to synthesize this property
@interface A ()
@property (nonatomic) NSInteger hiddenValue;
@end
// the implementation might initialize this property
@implementation A
- (id)init {
self = [super init];
if (self) {
_hiddenValue = 42;
}
return self;
}
@end
Then consider this category:
// A+Protected.h
@interface A (Protected)
@property (readonly, nonatomic) NSInteger hiddenValue;
@end
Note, this extension doesn't synthesize the hiddenValue
(the private extension in A
does that). But this provides a mechanism for anyone who imports A+Protected.h
to have access to this property. Now, in this example, while hiddenValue
is really readwrite
(as defined in the private extension within A
), this category is exposing only the getter. (You obviously could omit readonly
if you wanted it to expose both the getter and the setter, but I use this for illustrative purposes.)
Anyway, B
can now do things like:
// B.h
#import "A.h"
@interface B : A
- (void)experiment;
// but again, no properties exposed
@end
And
// B.m
#import "B.h"
#import "A+Protected.h"
@implementation B
// but with this category, B now has read access to this `hiddenValue`
- (void)experiment {
NSLog(@"%ld", (long)self.hiddenValue);
}
@end
Now A
isn't exposing hiddenValue
, but any code that uses this A (Protected)
category (in this case, just B
) can now access this property.
And so now you can call B
methods that might be using the hiddenValue
from A
, while never exposing it in the public interfaces.
// ViewController.m
#import "ViewController.h"
#import "B.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
B *b = [[B alloc] init];
[b experiment]; // this calls `B`’s exposed method, and that method is using the property not exposed by `A.h`
}
@end
If you're interested in a real-world example of this, consider UIKit's:
@import UIKit.UIGestureRecognizerSubclass;
Generally the state
of a UIGestureRecognizer
is readonly
, but this UIGestureRecognizer (UIGestureRecognizerProtected)
category exposes the readwrite
accessors for state
(to be used, as the name suggests, by gesture recognizer subclasses only).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.