6

当对列出 .h 文件中的私有 ivars 的 Apple 类进行子类化时,是否可以在子类 .m 文件中的类扩展 @interface 中重新声明您自己的子类中的这些 ivars,以便您的子类实现可以访问它们?

4

2 回答 2

8

您必须记住,在子类中声明实例变量不会重新声明具有相同名称的现有超类实例变量,无论声称的重新声明是在公共接口中还是在类扩展中。即使您使用相同的名称,它也是一个不同的实例变量

你可以自己试试这个。例如:

@interface Base : NSObject {
@private
    int _number;
}
@end

@implementation Base
- (id)init { self = [super init]; if (self) _number = 10; return self; }
- (void)logNumber { printf("base = %d\n", _number); }
@end

@interface Derived : Base
@end

@interface Derived () {
    int _number;
}
@end

@implementation Derived
- (id)init { self = [super init]; if (self) _number = 20; return self; }
- (void)logNumberDerived { printf("derived = %d\n", _number); }
@end

int main(void) {
    Derived *o = [Derived new];
    [o logNumber];
    [o logNumberDerived];
    return 0;
}

输出:

base = 10
derived = 20

因为_number在超类中不同于_number在子类中(扩展)。如果您使用 来检查二进制输出中的符号nm -a,您会注意到编译器会生成两个不同的符号:

s _OBJC_IVAR_$_Base._number
s _OBJC_IVAR_$_Derived._number
于 2013-06-19T11:14:43.717 回答
3

我在这里找到了与我自己完全匹配的答案:http: //lists.apple.com/archives/cocoa-dev/2007/Feb/msg00939.html

如果他们将其设为@private 而不是@protected,您将不得不假设这是有原因的。这个原因当然可能只是谨慎的做法是把所有东西都设为@private,直到你知道有充分的理由不...

也就是说,即使在技术上是可行的,直接访问它也绝对不能确定。

安全的做法是在您自己的类中重新做所有事情,同时请求超类的维护者在公共/受保护接口中公开您需要的功能。

于 2013-06-19T09:33:05.917 回答