基本的に、私は次のようなクラス階層を持っています。
NSObject
MySpecialController
MyExtraSpecialController
これらのそれぞれにinitメソッドがあり、各実装はsuper最初に呼び出して、スーパークラスが最初にそれ自体を初期化するようにします。より良い用語がないため、各クラスはそのスーパークラスの動作を「強化」していると言えます。
しかし、スーパークラスの動作を完全に「置き換え」たいとしましょう(特定のアプリにさらに特化したいのですが、一般的な再利用可能なスーパークラスを乱雑にすることはありません。したがって、スーパークラスについての深い知識があると想定されます。 )。私がしたい実際の変更は、プロパティをより具体的なクラスタイプの1つに置き換えることです。これを完全に実装するには、適切なクラスのinitインスタンスをインスタンス化するメソッドが必要です。widgetしたがって、をインスタンス化する場合MySpecialController、そのwidgetプロパティはMySpecialWidget;型である必要があります。しかし、私がインスタンス化する場合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、そのスーパークラスが最初にをインスタンス化しMySpecialWidget、次にそのインスタンスの割り当てをすぐに解除して、のインスタンスに置き換えますMyExtraSpecialWidget。確かにこれは機能しますが、私はスーパークラスについての深い知識を持っているので(つまり、基本的にそのinitメソッドが何をするのかを正確に知っているので、最初に呼び出す必要なしに安全に置き換えることができます)、この問題を回避してインスタンス化するだけです単一のウィジェット(ウィジェットの作成は非常に費用がかかり、時期尚早の最適化ではありません)。だから私はスーパーの実装を完全に置き換えてウィジェットを作成せず、私の親密な知識に基づいてそれが行う他のすべてを置き換えたいと思っていますが、これが重要です、私はまだ呼び出したいですinitinit置き換えられたクラスの「スーパークラス」メソッド(NSObjectこの場合)が何をするのかわからないため、チェーンのさらに上流にあります。これは、私が詳しく知らないクラスであるためです。
頭に浮かぶ当面の解決策は、Objective-C動的ランタイムを使用して祖父母インスタンスを取得し、そのインスタンスを呼び出すだけですinit(必要に応じてチェーンの呼び出しを処理します)。これにより、superをバイパスします。しかし、私がそのようなことをしようとしているときはいつでも、より良いアプローチがあるかどうか常に疑問に思います-概念的に言えば、つまり、スーパークラスのメソッドを拡張するのではなく置き換えることです。ある?