私は、Code Completeの Steve McConnellが言及したものと非常によく似た状況にあります。私の問題が車とトライクに基づいているということだけが、たまたま法律で車のカテゴリに分類されることにあります。今までの車は四輪でした。とにかく、私のドメインは不必要に複雑なので、以下の猫の例に固執するのは簡単です.
ルーチンをオーバーライドし、派生ルーチン内で何もしないクラスを疑ってください。これは通常、基本クラスの設計に誤りがあることを示しています。たとえば、クラス Cat とルーチン Scratch() があり、最終的に何匹かの猫の爪が剥がれて引っ掻くことができないことがわかったとします。ScratchlessCat という名前の Cat から派生したクラスを作成し、何もしないように Scratch() ルーチンをオーバーライドしたくなるかもしれません。このアプローチにはいくつかの問題があります。
インターフェイスのセマンティクスを変更することにより、Cat クラスで提示される抽象化 (インターフェイス コントラクト) に違反します。
このアプローチは、他の派生クラスに拡張するとすぐに制御不能になります。しっぽのない猫を見つけたらどうしますか?それともねずみを捕まえない猫?それともミルクを飲まない猫?最終的には、ScratchlessTaillessMicelessMilklessCat のような派生クラスになります。
時間が経つにつれて、このアプローチは維持するのに混乱を招くコードを生み出します。これは、祖先クラスのインターフェイスと動作が、その子孫の動作についてほとんど、またはまったく意味を持たないためです。
この問題を修正する場所は、基本クラスではなく、元の Cat クラスにあります。Claws クラスを作成し、それを Cats クラス内に含めます。根本的な問題は、すべての猫が引っ掻くという仮定でした。そのため、目的地で包帯を巻くのではなく、発生源でその問題を修正してください。
上記の彼の偉大な本のテキストによると. フォローが悪い
親クラスは抽象である必要はありません
public abstract class Cat {
public void scratch() {
System.out.println("I can scratch");
}
}
派生クラス
public class ScratchlessCat extends Cat {
@Override
public void scratch() {
// do nothing
}
}
現在、彼は別のクラスを作成することを提案しClaws
ていますが、このクラスを使用して の必要性を回避する方法がわかりませんScratchlessCat#Scratch
。