objective-c – 用init方法替换self是一种不好的做法吗?
我从Appledoc那里读到了关于着名(或臭名昭着的?)init方法的内容
所以说我有这两个班 @interface A : NSObject @end @interface B : A @property (nonatomic,strong) NSArray *usefulArray; @end 具有以下实现 @implementation A +(NSMutableArray *)wonderfulCache { static NSMutableArray *array = nil; if (!array) array = [NSMutableArray array]; return array; } -(id)init { if (self=[super init]) { // substituting self with another object // A has thought of an intelligent way of recycling // its own objects if ([self.class wonderfulCache].count) { self = [self.class wonderfulCache].lastObject; [[self.class wonderfulCache] removeLastObject]; } else { // go through some initiating process // .... if (self.canBeReused) [[self.class wonderfulCache] addObject:self]; } } return self; } -(BOOL) canBeReused { // put in some condition return YES; } @end @implementation B -(id)init { if (self=[super init]) { // setting the property self.usefulArray = [NSArray array]; } return self; } @end 当B调用init时,[super init]可能会返回一个替换的A对象,当B尝试设置属性(A没有)时,它不会导致错误吗? 如果这确实导致错误,我们如何以正确的方式实现上述模式? 更新:附加更真实的特定问题 这是一个名为C的C类(其用法将在后面解释) class C { /// Get the user data pointer void* GetUserData() const; /// Set the user data. Use this to store your application specific data. void SetUserData(void* data); } 说A的目的是充当C的包装;并且始终在A和C之间保持一对一的关系至关重要. 所以我想出了以下的接口和实现 @interface A : NSObject -(id)initWithC:(C *)c; @end @implementation A { C *_c; } -(id)initWithC:(C *)c { id cu = (__bridge id) c->GetUserData(); if (cu) { // Bingo,we've got the object already! if ([cu isKindOfClass:self.class]) { return (self = cu); } else { // expensive operation to unbind cu from c // but how...? } } if (self=[super init]) { _c = c; c->SetUserData((__bridge void *)self); // expensive operation to bind c to self // ... } return self; } @end 这暂时适用.现在我想把A分类,所以我想出了B. @interface B : A @property (nonatomic,strong) NSArray *usefulArray; @end 现在出现问题,因为A不知道如何正确解除绑定实例.所以我必须修改上面的代码 @interface A : NSObject { C *_c; } -(id)initWithC:(C *)c; -(void) bind; -(void) unbind; @end @implementation A -(id)initWithC:(C *)c { id cu = (__bridge id) c->GetUserData(); if (cu) { // Bingo,we've got the object already! if ([cu isKindOfClass:self.class]) { return (self = cu); } else { NSAssert([cu isKindOfClass:[A class]],@"inconsistent wrapper relationship"); [(A *)cu unbind]; } } if (self=[super init]) { _c = c; c->SetUserData((__bridge void *)self); [self bind]; } return self; } -(void) bind { //.. do something about _c } -(void) unbind { // .. do something about _c _c = nil; } @end 现在B只需要覆盖bind和unbind就能使它工作. 但是当我想到它时,所有B想要做的就是有一个额外的数组有用,它是否真的值得这么多工作……?编写unbind只是为了让你的子类以与C对象的1对1关系替换你的想法看起来很奇怪(而且效率也很低). 解决方法
似乎有一个误解:
init方法必须始终返回接收类类型的实例. 如果 – [A init]在[B init]中通过[super init]调用,则self为a (已分配但尚未初始化)B类实例.因此 – [初始化] 必须返回B类(或子类)的实例. 因此,如果您决定“回收”对象,则必须确保该对象 我不知道在你的情况下“在init中替换self”是不是很糟糕的做法可能取决于对象和canBeReused条件.它主要是由“类集群”,如NSNumber,NSArray等. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |