实例variables的类别类扩展

有没有办法以某种方式来模仿类的行为,而不是类的实例variables,而不是方法?

我有一个ClassA ,我想保留它的名字后,用新的方法和其他cllass( ClassB )的Ivars。 当然,我可以inheritanceClassA ,但是结果类会有不同的名称。

对于方法的补充,这不是一个问题 – 类别将是一个很好的解决scheme。

更新: ClassA用作XIB的文件所有者 ,这些要扩展的字段是IBOutlet 。 所以我需要在构build阶段。

由于iPhone使用了现代的Objective-C运行库,因此可以使用关联引用将数据添加到实例,而无需声明实例variables。 请参阅objc_setAssociatedObject等的文档

如果您使用标准存取方法将调用包装到运行时,它将非常易于使用。

我已经调查了关于联合引用 (感谢Ole )玩这个问题,方法静态variables,方法swizzling,最后来到这个简单的解决scheme(没有运行时的东西)。 我只是简单地使用“分类”类来返回一个指向派生类的指针,这当然可以包含额外的Ivars。 这样做我可以获得一个意想不到的好处:我可以调用super类的方法,这在扩展时是不可能的。

类扩展的例子( testing ):

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 (分类方式);
  • ClassBinheritanceClassAClassB可以调用ClassA方法);
  • ClassB可以通过ClassA名称(类别的方式)

我把Martin的例子放到一个简单的应用程序中,使用NSDatareplaceClassA,使用XXDatareplaceClassB,使用getIvarreplaceonClick,然后调用它(Mac OS X 10.6.6,Xcode 4 Final):

 NSData * data = [NSData data]; NSLog(@"%@", [data getIvar]); 

它失败了“ – [NSConcreteData getIvar]:无法识别的select器发送到实例”..

它失败了,因为NSData类别中的“alloc”(它返回指向派生类的指针)不被上面的代码调用。 如果,而是明确地调用“alloc”,如下所示:

 NSData * data = [[NSData alloc] init]; NSLog(@"%@", [data getIvar]); 

那么一切都很好。