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等. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
