抽象クラスとそのクラスの派生クラスがある場合、適切で実用的な設計慣行に従って、派生クラスは追加のパブリック メソッドを提供しないこと (抽象クラスのみを実装し、必要に応じて親メソッドをオーバーライドする必要があります) で正しいでしょうか?
さらに、派生クラスごとに異なるコンストラクター メソッド シグネチャを使用することは許容されるのでしょうか?
抽象クラスとそのクラスの派生クラスがある場合、適切で実用的な設計慣行に従って、派生クラスは追加のパブリック メソッドを提供しないこと (抽象クラスのみを実装し、必要に応じて親メソッドをオーバーライドする必要があります) で正しいでしょうか?
さらに、派生クラスごとに異なるコンストラクター メソッド シグネチャを使用することは許容されるのでしょうか?
個人的にはどちらでも問題ないと思います。
派生クラスの追加のパブリック メソッドについては、次のとおりです。
多くの場合、これには限られた有用性があります。クラスがキャストされているか、基本クラスへの参照に設定されている場合、追加のメソッドは使用できません。これにより、この方法の有用性が大幅に制限されます。そうは言っても、このアプローチには特に問題はありません。サブクラスは、特定の動作を追加することを目的としています。クラス階層では、サブクラスに基本クラスに適していない新しい動作が含まれることがあります。サブクラスが単独で頻繁に使用される場合、追加の動作をメソッドでモデル化することは完全に合理的と思われます。
コンストラクターの署名については -
これも問題ないと思います。多くの場合、サブクラスは、抽象クラスよりも多くの情報を使用可能な状態にする必要があります。そうは言っても、私は通常、すべてのコンストラクターを基本クラスに実装し、さらにサブクラスに必要な新しいパラメーターを追加します。
そうは言っても:
正当な理由がない限り、基本クラスよりも少ないパラメーターを持つサブクラス コンストラクターを使用することは避けます...特定のケースではなく、より一般的なケースで何かを指定できるのはなぜですか? サブクラスに基本クラスとはまったく異なる構築オプションがある場合、通常は混乱することがわかります。
これが派生クラスの利点です。
Pen クラスには write() 関数が含まれる場合がありますが、Pen を拡張する RetractablePen クラスには、retractPoint() 関数も含まれる場合があります。
クラスを拡張するということは、文字通り、その機能を拡張することを意味します。
おおむね順調です。
避けたいのは、ジェネリックで特定のものを使用することです。すなわち
foreach(Animal a in myFarm.Animals)
{
a.Feed();
// this is a bit grim
if( a is Horse )
{
((Horse)a).CleanStable();
}
}
つまり、パブリック メソッドを追加するという行為ではなく、どこから呼び出すかということです。
Liskov の置換原理を尊重すれば、やりたいことができます。
もちろん、派生クラスにメソッドを追加することは原則にまったく違反しません。
派生クラスに追加のパブリック メソッドを追加することはまったく問題ありません。それらに異なるコンストラクターを与えることも完全に受け入れられます。(実際、これは非常に一般的です。)
いいえ、追加のパブリック メソッドを追加することは完全に合理的です (時には設計上非常に必要です)。メンバーとメソッドShape
を持つ抽象基本クラスの (完全に考案された) 状況を考えてみましょう。たとえば、から派生する場合、たとえば、 というパブリック メソッドを追加することができます。しかし、から派生するときにそれを持ちたくありません。Location
Size
Polygon
Shape
GetNumberOfSides()
Circle
Shape
同様に、派生型の構築要件は大きく異なる場合があります。抽象基本クラスを定義するときにすべての要件が何であるかを知ることは実際には不可能であるため、自由に異なるシグネチャを使用してください。派生型が抽象基本クラスに対して多態的であるからといって、その基本クラスで定義された抽象化を実装する方法にその基本クラスが厳密な制限を課すわけではありません。好きなようにほとんど自由にできます。
これは許容されるだけでなく、多くの場合、コンストラクターが異なる必要があります。たとえば、 (immutable)Rectangle
クラスがあり、それを (immutable) で拡張する場合Square
、Square のコンストラクターは (当面 Java を使用するため) にする必要があります。
public Square(double size)
一方、のコンストラクターRectangle
は
public Rectangle(double width, double height)
必要なことは、サブクラス コンストラクターが適切なスーパークラス コンストラクターを呼び出す必要があることです。
追加のパブリック メソッドについては、用途に依存する場合があります。Square の場合、追加のメソッドは追加しません。ただし、Java には、
いくつかの便利なメソッドを追加することを目的としたサブクラスPrintWriter
があります。Writer
この場合、問題ないと思います (Java には確かに悪い例がいくつかありますが、これはその 1 つではないと思います)。また、コンテナ/サブパーツ タイプ用のいくつかの追加メソッドの可能性も期待できます。
すべきでないことは、スーパー クラスの期待に反する方法でスーパー クラスのメソッドを変更することです。
派生クラスは、追加のパブリック メソッドを提供してはなりません
動物にできないことを犬はできるのか?
さらに、派生クラスごとに異なるコンストラクター メソッド シグネチャを使用することは許容されるのでしょうか?
ここは問題ありません。派生型は、兄弟または親のコンストラクター シグネチャと一致する必要はありません。