【发布时间】:2013-06-15 18:37:08
【问题描述】:
当对列出 .h 文件中的私有 ivars 的 Apple 类进行子类化时,是否可以在子类 .m 文件内的类扩展 @interface 中重新声明您自己的子类中的这些 ivars,以使您的子类可以访问它们实施?
【问题讨论】:
标签: objective-c cocoa-touch cocoa subclass foundation
当对列出 .h 文件中的私有 ivars 的 Apple 类进行子类化时,是否可以在子类 .m 文件内的类扩展 @interface 中重新声明您自己的子类中的这些 ivars,以使您的子类可以访问它们实施?
【问题讨论】:
标签: objective-c cocoa-touch cocoa subclass foundation
我在这里找到了完全符合我自己的答案:http://lists.apple.com/archives/cocoa-dev/2007/Feb/msg00939.html
如果他们将其设为@private 而不是@protected,您将不得不假设 这是有原因的。这个原因当然可能只是 在您知道充分的理由之前,将所有内容都设为@private 是谨慎的 不要...
也就是说,它可能非常明确地不可以访问它 直接,即使技术上可行。
安全的做法是在你自己的课堂上重新做所有事情,同时 请求超类的维护者揭露 公共/受保护界面中所需的功能。
【讨论】:
您必须记住,在子类中声明实例变量不会重新声明具有相同名称的现有超类实例变量,无论声称的重新声明是在公共接口中还是在类扩展中.即使您使用相同的名称,它是不同的实例变量。
您可以自己尝试一下。例如:
@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
【讨论】: