如何在objective-c中模拟受保护的属性和方法 [英] How to simulate protected properties and methods in objective-c
问题描述
可能的重复:
objective-c 中的受保护方法
声明私有属性的方法很简单.
The way to declare private properties is simple.
您在 .m 文件中声明的扩展名中声明.
You declare that in extension that's declared in .m files.
假设我想声明受保护的属性并从类和子类访问它.
Say I want to declare protected properties and access it from the class and subclass.
这是我试过的:
//
// BGGoogleMap+protected.h
//
//
#import "BGGoogleMap.h"
@interface BGGoogleMap ()
@property (strong,nonatomic) NSString * protectedHello;
@end
那个是编译.然后我补充说:
That one is compile. Then I added:
#import "BGGoogleMap+protected.h"
@implementation BGGoogleMap ()
-(NSString *) protectedHello
{
return _
}
@end
问题开始了.我似乎无法在原始 .m 文件之外实现类扩展.Xcode 将要求该括号内的某些内容.
Problem starts. I can't implement class extension outside the original .m files it seems. Xcode will demand something inside that bracket.
如果我这样做
#import "BGGoogleMap+protected.h"
@implementation BGGoogleMap (protected)
-(NSString *) protectedHello
{
return _
}
@end
我无法访问 BGGoogleMap+protected.h 中声明的 _protectedHello 的 ivar
I cannot access the ivar of _protectedHello declared in BGGoogleMap+protected.h
当然我可以使用常规类别而不是扩展名,但这意味着我不能拥有受保护的属性.
Of course I can use regular category rather than extension, but that means I can't have protected properties.
那我该怎么办?
推荐答案
Objective-C 编程语言是这样说的:
类扩展类似于匿名类别,除了它们声明的方法必须在相应类的主 @implementation
块中实现.
Class extensions are like anonymous categories, except that the methods they declare must be implemented in the main
@implementation
block for the corresponding class.
因此,您可以在类的主要 @implementation
中实现类扩展的方法.这是最简单的解决方案.
So you could just implement your class extension's methods in the class's main @implementation
. That is the simplest solution.
更复杂的解决方案是在类别中声明您的受保护"消息和属性,并在类扩展中声明该类别的任何实例变量.这是类别:
A more complicated solution is to declare your "protected" messages and properties in a category, and declare any instance variables for that category in a class extension. Here's the category:
#import "BGGoogleMap.h"
@interface BGGoogleMap (protected)
@property (nonatomic) NSString * protectedHello;
@end
由于类别不能添加实例变量来保存protectedHello
,我们还需要一个类扩展:
Since a category cannot add an instance variable to hold protectedHello
, we need a class extension also:
#import "BGGoogleMap.h"
@interface BGGoogleMap () {
NSString *_protectedHello;
}
@end
我们需要在主 @implementation
文件中包含类扩展,以便编译器在 .o
文件中发出实例变量:
We need to include the class extension in the main @implementation
file so that the compiler will emit the instance variable in the .o
file:
#import "BGGoogleMap.h"
#import "BGGoogleMap_protectedInstanceVariables.h"
@implementation BGGoogleMap
...
并且我们需要在类别@implementation
文件中包含类扩展,以便类别方法可以访问实例变量.由于我们在类别中声明了 protectedHello
属性,编译器将不合成 setter 和 getter 方法.我们必须手工编写它们:
And we need to include the class extension in the category @implementation
file so that the category methods can access the instance variables. Since we declared the protectedHello
property in a category, the compiler will not synthesize the setter and getter method. We have to write them by hand:
#import "BGGoogleMap+protected.h"
@implementation BGGoogleMap (protected)
- (void)setProtectedHello:(NSString *)newValue {
_protectedHello = newValue; // assuming ARC
}
- (NSString *)protectedHello {
return _protectedHello;
}
@end
子类应该导入 BGGoogleMap+protected.h
才能使用 protectedHello
属性.它们不应导入 BGGoogleMap_protectedInstanceVariables.h
,因为实例变量应被视为基类的私有变量.如果您发布一个没有源代码的静态库,并且您希望库的用户能够继承 BGGoogleMap
,请发布 BGGoogleMap.h
和 BGGoogleMap+protected.h
标头,但不要传送 BGGoogleMap_protectedInstanceVariables.h
标头.
Subclasses should import BGGoogleMap+protected.h
to be able to use the protectedHello
property. They should not import BGGoogleMap_protectedInstanceVariables.h
because the instance variables should be treated as private to the base class. If you ship a static library without source code, and you want users of the library to be able to subclass BGGoogleMap
, ship the BGGoogleMap.h
and BGGoogleMap+protected.h
headers, but don't ship the BGGoogleMap_protectedInstanceVariables.h
header.
这篇关于如何在objective-c中模拟受保护的属性和方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!