基本上我有一个像这样的类层次结构:
NSObject
MySpecialController
MyExtraSpecialController
它们中的每一个都有一个init
方法,并且每个实现首先调用super
以让超类首先初始化自己,一直到链上。由于缺乏更好的术语,我会说每个类都“增强”了它的超类的行为。
但是让我们假设我想完全“替换”我的超类的行为(仅仅是因为我想为特定的应用程序进一步专门化它,但又不会弄乱通用的可重用超类。所以假设我对超类有深入的了解)。我想要做的实际更改是将属性替换为更具体的类类型之一。为了完全实现这一点,我需要init
实例化widget
适当类的实例的方法。所以如果我实例化 a MySpecialController
,它的widget
属性应该是 type MySpecialWidget
;但如果我实例化 a MyExtraSpecialController
,它widget
应该是类型MyExtraSpecialWidget
:
//MySpecialController:
@interface MySpecialController : NSObject
@property (strong, nonatomic) MySpecialWidget *widget;
@end
@implementation MySpecialController
-(id)init {
if (self = [super init]) {
self.widget = [MySpecialWidget new];
}
}
@end
//MyExtraSpecialController:
@interface MyExtraSpecialController : MySpecialController
@property (strong, nonatomic) MyExtraSpecialWidget *widget;
@end
@implementation MyExtraSpecialController
-(id)init {
if (self = [super init]) {
self.widget = [MyExtraSpecialWidget new];
}
}
@end
现在,这在某种意义上是MySpecialController
有效的,并且可以被任何拥有公共 API 的人使用。而且MyExtraSpecialController
也有效,并且遵循适当的关注点分离,因为它对超类的行为没有任何假设。这是为框架或库类创建的子类类型:健壮且不张扬。
但实际发生的是,当我创建 的新实例时MyExtraSpecialController
,它的超类首先实例化 a MySpecialWidget
,然后立即释放该实例并将其替换为 的实例MyExtraSpecialWidget
。当然这可行,但由于我对超类有深入的了解(这基本上意味着我确切地知道它的init
方法做了什么,所以我可以安全地替换它而无需先调用它),我想避免这个问题并且只实例化一个小部件(碰巧创建一个小部件真的很昂贵,而且不是过早的优化)。所以我想完全替换 super 的实现,这样它就不会创建一个小部件,并且会根据我的知识替换它所做的所有其他事情,但是,这是关键,我仍然想调用init
更进一步,因为我不知道我替换的类的“超类”init
方法做了什么(NSObject
在这种情况下),因为这是一个我不熟悉的类。
想到的直接解决方案是使用 Objective-C 动态运行时来获取祖父实例,然后调用它init
(如果需要,它将负责调用链),从而绕过 super。但是每当我发现自己要做类似的事情时,我总是想知道是否有更好的方法——从概念上讲,即替换而不是增加超类的方法。在那儿?