クラスカテゴリを使用して、カテゴリを使用して既に実装されているメソッドをオーバーライドできますか?このような:
1)独自の方法
-(BOOL) method {
return true;
}
2)オーバーライドされたメソッド
-(BOOL) method {
NSLog(@"error?");
return true;
}
これは機能しますか、それとも違法ですか?
回答:
アップルのドキュメントから:
現在、Objective-C言語では、カテゴリを使用して、クラスが継承するメソッド、またはクラスインターフェイスで宣言されたメソッドをオーバーライドすることができますが、そうすることはお勧めしません。カテゴリはサブクラスの代わりにはなりません。カテゴリを使用してメソッドをオーバーライドすることには、いくつかの重大な欠点があります。
カテゴリが継承されたメソッドをオーバーライドすると、カテゴリ内のメソッドは通常どおり、へのメッセージを介して継承された実装を呼び出すことができます
super
。ただし、カテゴリがそのカテゴリのクラスに存在するメソッドをオーバーライドする場合、元の実装を呼び出す方法はありません。カテゴリは、同じクラスの別のカテゴリで宣言されたメソッドを確実にオーバーライドすることはできません。
Cocoaクラスの多くはカテゴリを使用して実装されているため、この問題は特に重要です。オーバーライドしようとするフレームワーク定義のメソッド自体がカテゴリに実装されている可能性があるため、どの実装が優先されるかは定義されていません。
一部のカテゴリメソッドが存在すると、すべてのフレームワークで動作が変化する可能性があります。たとえば、
windowWillClose:
NSObjectのカテゴリでデリゲートメソッドをオーバーライドすると、プログラム内のすべてのウィンドウデリゲートは、カテゴリメソッドを使用して応答します。NSWindowのすべてのインスタンスの動作が変わる可能性があります。フレームワーククラスに追加したカテゴリは、動作に不可解な変化を引き起こし、クラッシュを引き起こす可能性があります。
これを行うには、クラスクラスターアプローチを採用するか、メソッドスウィズリングテクニックを使用します。
それ以外の場合、2つ以上の分類されたメソッドの動作は未定義です
古いドキュメントのリンクは死んでいます。私が見つけた最高の代替品はここにありました:Apple Docs:
カテゴリメソッド名の衝突を回避する
カテゴリで宣言されたメソッドは既存のクラスに追加されるため、メソッド名には細心の注意が必要です。
カテゴリで宣言されたメソッドの名前が元のクラスのメソッド、または同じクラス(またはスーパークラス)の別のカテゴリのメソッドと同じである場合、どのメソッド実装が使用されるかについての動作は未定義です。ランタイム。独自のクラスでカテゴリを使用している場合、これは問題になる可能性は低いですが、カテゴリを使用して標準のCocoaまたはCocoa Touchクラスにメソッドを追加するときに問題が発生する可能性があります。
軽いタッチを使用しているのはAppleですが、要点は同じです。予測できない動作は静かなので、災害を招きます。
カテゴリを使用して、基本クラスの既存のメソッド(たとえば、Carクラスのドライブメソッド)をオーバーライドすることもできますが、これを行うことはできません。問題は、カテゴリーがフラットな組織構造であることです。Car + Maintenance.mの既存のメソッドをオーバーライドし、その動作を別のカテゴリで再度変更することにした場合、Objective-Cが使用する実装を知る方法はありません。このような状況では、ほとんどの場合サブクラス化の方が適しています。
このチュートリアルから、http://rypress.com/tutorials/objective-c/categories