我有A
类,它的.m
文件中有此声明:
@implementation A {
NSObject *trickyObject;
}
并且在B
文件中具有此声明的类.h
:
@interface B : A
@end
是否有可能从类trickyObject
中声明的方法访问B
?
[如果您拥有私有的属性或方法,但是您想让子类可以访问,则可以将声明放在category中。
所以考虑A
:
// A.h
@import Foundation;
@interface A : NSObject
// no properties exposed
@end
和
// 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
然后考虑此类别:
// A+Protected.h
@interface A (Protected)
@property (readonly, nonatomic) NSInteger hiddenValue;
@end
[注意,此扩展名无法合成hiddenValue
(A
中的私人扩展名可以这样做)。但这为导入A+Protected.h
的任何人提供了访问此属性的机制。现在,在此示例中,虽然hiddenValue
实际上是readwrite
(如A
中的私有扩展中所定义),但此类别仅公开getter。 (显然,如果您希望它同时公开getter和setter,则可以省略readonly
,但我将其用于说明目的。)
无论如何,B
现在可以执行以下操作:
// B.h
#import "A.h"
@interface B : A
- (void)experiment;
// but again, no properties exposed
@end
和
// 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
现在A
不会公开hiddenValue
,但是任何使用此A(Protected)
类别的代码(在这种情况下,仅是B
)现在都可以访问此属性。
所以现在您可以从B
调用可能正在使用hiddenValue
的A
方法,而不必在公共接口中公开它。
// ViewController.m
#import "ViewController.h"
#import "B.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
B *b = [[B alloc] init];
[b experiment];
}
@end
如果您对此示例感兴趣,请考虑:
@import UIKit.UIGestureRecognizerSubclass;
[state
的UIGestureRecognizer
通常是readonly
,但此UIGestureRecognizer (UIGestureRecognizerProtected)
类别公开了readwrite
的state
访问器(顾名思义,仅用于手势识别器子类)。