在允许[super init]时阻止ObjC“抽象”类“init方法被调用?

问题描述:

说我有一个用户不应该实例化的伪抽象基类。基本上我想在他们试图调用该类的init时发出警告,或者返回具有默认值的具体实例之一。在允许[super init]时阻止ObjC“抽象”类“init方法被调用?

但是,该基类的具体实现必须在其初始值设定项中调用[super init]。这当然应该允许。

我该如何做到最好?

我在想,这应该是罚款:

@implementation KTPhysicsShape 
-(id) init 
{ 
    // throw exception here or return concrete instance with default values 
} 

// this is what subclasses would call in place of [super init]: 
-(id) internal_initFromSubclass 
{ 
    return [super init]; 
} 
@end 

对这种做法的任何问题?我知道其他人仍然可以调用内部方法,但我最担心的是禁止init,因为这是用户尝试称之为最重要的。

+0

看起来很不错。但是如果你在init中调用'internal_initFromSubclass'而不是抛出异常。这样,只有你的方法可以初始化对象。 – samfisher 2013-04-05 15:22:09

我也在如何有效地抽象类的问题上工作,但我不是这个解决方案。在我看来,它会让你的子类代码看起来奇怪,难以阅读,供临时观察者阅读。

如果您需要您的子类在-init中进行特定初始化,那么您可能是唯一的解决方案。但是,如果你只是想确保他们已经子类,你可以做内-init

-(id) init 
{ 
    NSAssert(![self isMemberOfClass:[KTPhysicsShape class]], 
             @"KTPhysicsShape must be subclassed!"); 
    return [super init]; 
} 
+0

我想你想'isMemberOfClass:' – 2013-04-05 15:28:52

+0

谢谢,迈克。在我看来,它是“那种不是'-isKindOfClass:'的方法。” – 2013-04-05 15:31:24

+0

@SeamusCampbell不应该自己分配? – 2013-04-05 15:36:29

这表示您的架构有一个严重的缺陷。指定初始化链的全部重点在于它可以按照可预测的顺序执行而不会发生变化。将子类别的合同义务添加到而不是遵循正常的链条增加了脆弱性和不必要的复杂性。

缺陷的症结在于你有一个抽象类,看起来并不真正抽象;它可以有具体的实例,并且需要具体的初始化。

首先,你为什么不能把课堂分解成真正的抽象类和具体类?

如果你不能(或不愿 - 当然,更多的类都有自己的成本),那么一个解决办法是打出来的常用的初始化操作成一个单独的方法:

- (void) commonKTPhysicsShapeInit 
{ 
    .... 
} 

那不叫super这不会在您的标题中声明;它是一个内部到实现的方法,因此也就是名称。

然后,让你的子类调用commonInit的标准指定初始化程序。对于该类的具体实例,有一个单独的初始化程序,它们都调用commonInit并执行具体的初始化跳舞。

它与您的建议类似,但以更贴近现有模式的方式呈现界面。

+0

完全同意不打破初始链......我之所以问的一个原因 – LearnCocos2D 2013-04-05 16:02:11