从Objective-C的子类访问ivar

问题描述 投票:2回答:1

我有A类,它的.m文件中有此声明:

@implementation A {
    NSObject *trickyObject;
}

并且在B文件中具有此声明的类.h

@interface B : A
@end

是否有可能从类trickyObject中声明的方法访问B

objective-c subclass superclass ivar
1个回答
1
投票

[如果您拥有私有的属性或方法,但是您想让子类可以访问,则可以将声明放在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

[注意,此扩展名无法合成hiddenValueA中的私人扩展名可以这样做)。但这为导入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调用可能正在使用hiddenValueA方法,而不必在公共接口中公开它。

//  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;

[stateUIGestureRecognizer通常是readonly,但此UIGestureRecognizer (UIGestureRecognizerProtected)类别公开了readwritestate访问器(顾名思义,仅用于手势识别器子类)。

© www.soinside.com 2019 - 2024. All rights reserved.