Это возможно при использовании расширения класса (не категории), которое вы включаете в файлы реализации базового класса и подклассов.
Расширение класса определяется аналогично категории, но без категорииname:
@interface MyClass ()
В расширении класса вы можете объявить свойства, которые смогут синтезировать вспомогательные ivars (XCode> 4.4, автоматический синтез ivars также работает здесь).
В классе расширений вы можете переопределить / уточнить свойства (изменить только чтение на чтение и т. Д.) И добавить свойства и методы, которые будут «видимы» для файлов реализации (но обратите внимание, что свойства и методы на самом деле не являются частными и могутвсе еще вызывается селектором).
Другие предложили использовать для этого отдельный заголовочный файл MyClass_protected.h, но это также можно сделать в главном заголовочном файле, используя #ifdef
, например:
Пример:
BaseClass.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
BaseClass.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
ChildClass.h
// this will import BaseClass.h without the class extension
#import "BaseClass.h"
@interface ChildClass : BaseClass
-(void)test;
@end
ChildClass.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
, чтобы компилятор включал расширение защищенного класса.