这可以通过使用包含在基类和子类的实现文件中的类扩展(不是类别)来实现。
类扩展的定义类似于类别,但没有类别名称:
@interface MyClass ()
在类扩展中,您可以声明属性,这些属性将能够合成支持的 ivars(XCode > 4.4 自动合成 ivars 也适用于此)。
在扩展类中,您可以覆盖/优化属性(将只读更改为读写等),并向实现文件添加“可见”的属性和方法(但请注意,属性和方法并不是真正私有的,可以仍然被选择器调用)。
其他人建议为此使用单独的头文件 MyClass_protected.h ,但这也可以在主头文件中使用#ifdef
,如下所示:
例子:
基类.h
@interface BaseClass : NSObject
// foo is readonly for consumers of the class
@property (nonatomic, readonly) NSString *foo;
@end
#ifdef BaseClass_protected
// this is the class extension, where you define
// the "protected" properties and methods of the class
@interface BaseClass ()
// foo is now readwrite
@property (nonatomic, readwrite) NSString *foo;
// bar is visible to implementation of subclasses
@property (nonatomic, readwrite) int bar;
-(void)baz;
@end
#endif
基类.m
// this will import BaseClass.h
// with BaseClass_protected defined,
// so it will also get the protected class extension
#define BaseClass_protected
#import "BaseClass.h"
@implementation BaseClass
-(void)baz {
self.foo = @"test";
self.bar = 123;
}
@end
子类.h
// this will import BaseClass.h without the class extension
#import "BaseClass.h"
@interface ChildClass : BaseClass
-(void)test;
@end
子类.m
// this will implicitly import BaseClass.h from ChildClass.h,
// with BaseClass_protected defined,
// so it will also get the protected class extension
#define BaseClass_protected
#import "ChildClass.h"
@implementation ChildClass
-(void)test {
self.foo = @"test";
self.bar = 123;
[self baz];
}
@end
当您调用时#import
,它基本上会将 .h 文件复制粘贴到您要导入它的位置。如果您有,则只有在设置了该名称的情况#ifdef
下,它才会包含其中的代码。#define
在您的 .h 文件中,您没有设置定义,因此任何导入此 .h 的类都不会看到受保护的类扩展。在基类和子类 .m 文件中,在使用#define
之前使用#import
,以便编译器包含受保护的类扩展。