有没有办法以某种方式模拟类的行为,而不是方法的实例变量?实例变量的类别扩展
我有一个ClassA
,我想保留它的名字后用新的方法和其他cllass的ivars(ClassB
)。 当然,我可以继承ClassA
,但生成的类会有不同的名称。
对于方法的补充,这不是问题 - 类别是一个很好的解决方案。
UPDATE:ClassA
用作文件所有者用于XIB,并且这些字段被扩展是IBOutlet
秒。所以我需要在构建阶段。
有没有办法以某种方式模拟类的行为,而不是方法的实例变量?实例变量的类别扩展
我有一个ClassA
,我想保留它的名字后用新的方法和其他cllass的ivars(ClassB
)。 当然,我可以继承ClassA
,但生成的类会有不同的名称。
对于方法的补充,这不是问题 - 类别是一个很好的解决方案。
UPDATE:ClassA
用作文件所有者用于XIB,并且这些字段被扩展是IBOutlet
秒。所以我需要在构建阶段。
我已经调查了这个问题玩associative references(感谢Ole),方法静态变量,方法swizzling,最后来到这个简单的解决方案(没有运行时的东西)。我只是简单地使用“分类”类来返回一个指向派生类的指针,这当然可以包含额外的Ivars。这样做我可以实现一个意想不到的好处:我可以拨打super
的班级方法,这在延伸类别时是不可能的。一类扩展的
实施例(测试):
ClassA的+ ClassB.h
@protocol _ClassB_Protocol
@optional // to avoid warnings
- (IBAction) onClick:(id)sender;
@property (nonatomic, retain) IBOutlet UIButton *aButton;
@end
@interface ClassA (_ClassA_Category) <_ClassB_Protocol>
@end
@interface ClassB: ClassA <_ClassB_Protocol> {
UIButton *aButton; // _ivar_ to add
}
@end
ClassA的+ ClassB.m
@implementation ClassA (_ClassA_Category)
// this will be called first on [ClassA alloc] or [ClassA allocWithZone:(NSZone *)zone]
+(id) alloc {
if ([self isEqual: [ClassA class]]) {
return [ClassB alloc];
} else {
return [super alloc];
}
}
@end
@implementation ClassB: ClassA
@synthesize aButton;
-(void) dealloc {
[aButton release];
[super dealloc]; // this is impossible for an ordinary category
}
- (void) onClick:(id)sender {
// some code here
}
@end
现在我们在同一时间:
ClassB
“扩展” ClassA
(分类方式);ClassB
继承ClassA
(ClassB
可以调用ClassA
方法);ClassB
可以通过ClassA
名称来访问(分类方式)由于iPhone使用了现代的Objective-C运行库,因此您可以使用associative references向实例添加数据,而无需声明实例变量。请参阅objc_setAssociatedObject
等文档。
如果使用标准存取方法将调用包装到运行时,它将非常易于使用。
用于运行时级别解决方案。但是,我使用`ClassA`作为**文件所有者**作为XIB,并且这些字段是`IBOutlets`。所以,我需要在构建阶段。对不起,没有指定这个细节。 – 2011-02-03 14:34:20
我把马丁的例子为一个平凡的应用程序与NSData的,ClassB的与XXData和的onClick与getIvar更换ClassA的,并调用它(的Mac OS X 10.6 。6时,Xcode 4最终)其中:
NSData * data = [NSData data];
NSLog(@"%@", [data getIvar]);
它失败 “ - [NSConcreteData getIvar]:无法识别的选择发送到实例” ..
它失败,因为 “黄金” 在NSData的类别(返回指向派生类的指针)不被上面的代码调用。如果明确地调用“alloc”,如:
NSData * data = [[NSData alloc] init];
NSLog(@"%@", [data getIvar]);
那么一切都很好。
它有一个新的名字有什么问题?如果你试图破解类继承,那么可能有更好的方法来做你想做的事情! – deanWombourne 2011-02-03 14:12:24
@deanWombourne:请查看更新后的问题。有时候,我们需要不寻常的方法。 – 2011-02-03 14:38:12