質問: タイトルの文面がどこで得た情報なのかが記憶が定かではないのですが、C#において、抽象クラスにはなるべく実装メソッドは書くべきではないと見聞きしたような覚えがあります。 しかし、上文の通り、どこで得た情報なのかが定かではなく、故に記憶違いの可能性もあり正しい知識なのか不安になったため、ここで質問させていただきます。 Webで調べてみても、解説しているコードの抽象クラス内に「抽象メソッド」と「実装されているメソッド」が混在しており、「タイトルの内容は間違いでは?」と半ば結論付けてはいるのですが、確信があるわけではありません。 参考までに、現在私が直面しているコードの内容を簡潔に一例として挙げさせていただきます。 【参考内容】 ※実装されているメソッドを「実装メソッド」と呼称します。 * 抽象クラスHogeBaseクラス内に、抽象メソッドHogeCalc、実装メソッドHogeDrawがある * HogeBaseクラスを基底クラスとし、複数の派生クラスを作成する。 * HogeManagerクラスは作成した各派生クラスのHogeDrawを呼ぶ。この時、派生クラスではHogeCalcを実装。その他の必要な初期化以外の記述は行わない。 * 派生クラス全てに共通した変数の初期化や計算、インスタンスの生成等はHogeBaseクラスで行う。 特に、この「派生クラス全てに共通した変数の初期化や計算、インスタンスの生成等はHogeBaseクラスで行う。」において、共通しているから基底クラスで実装しているものの「あくまで基底なんだからそこで初期化とか計算とか行うべきではない?」と考えてしまい、これがタイトルの内容につながっています。 長文になってしまい申し訳ありません。 何卒、正誤のご教授の方、よろしくお願いいたします。
回答: そもそもオブジェクト指向において継承はコードの共通化という目的のために存在していると思います。 コードの共通化という目的を満たさないのであれば、継承階層を構築してしまうというデメリットを支払えないと思います、抽象メソッドができることはシグニチャを縛ることでこれはコード量の削減には一切寄与しません。コードの共通化を行えるのは実装メソッドのみです。 設問者が提示する話ですが、処理の共通部を担うクラスHogeDrawへのインスタンスへの参照を保持し、処理の差分部をインターフェースIHogeCalcの実装とすれば、継承階層をなくすことができます。(いわゆる継承を使わず、コンポジションでの代用を試みるという設計原則) ここで重要なのがHogeDrawとHogeCalcの役割分担です。HogeDrawがクラスに関わらず不変となるようにCalcとの役割分担ができるのであれば、上記のような継承階層をなくすことが可能ですが、そうでない場合はおそらく継承を使うほうがいいのでしょう。 (継承を回避したいのは、C#がクラスの多重継承を認めないため、ある観点でのクラス階層を構築してしまうとある観点において階層を再構築しようとしてもうまくいかないから、現代的なオブジェクト指向は抽象クラスの継承よりもinterfaceによるmixinを推奨しているというのが主流であると私は考えています)