この記事ではオブジェクト指向の中でも重要なポジションである「抽象クラス」について、その基本的な使い方を紹介し、簡単なコンソールアプリケーションを作成していきます。
抽象クラスは抽象メソッドを持つクラスで、実体として生成することが特殊なクラスです。しかしながらオブジェクト指向においては重要な役割を果たしています。抽象クラスを使えるようになるとオブジェクト指向への理解度が一気に増したことになります。
抽象クラスの概要
冒頭でも簡単に紹介しましたが、抽象クラスとは「抽象」の世界でプログラミングを行うために必要な概念になります。抽象クラスは抽象メソッドを一つ以上持っているクラスとして定義されます。C#では「抽象」をabstractキーワードで表現しており、具体的な実装を持っていません。
イメージとしてはインターフェースに近い感じです。抽象クラスは以下のような感じで定義されます。
public abstract class Sample
{
public int Id { get; }
public abstract void DoSample();
public abstract string GetTitle();
}
上記のようにabstractで定義されたクラスには、abstractで定義されているメソッドが一つ以上必要となります。abstractメソッドには具体的な実装は記載せず、あくまでもメソッドとしての呼出口だけの定義を行います。通常のプロパティ・メソッドも普段通りに記載することが可能です。
抽象メソッドを継承したスーパークラスでは、インターフェースの時と同様に抽象メソッドとして定義された処理の具象部分を定義しなくてはなりません。スーパークラスとして以下のようになります。
スーパークラスにおいて具体的な実装をコーディングする場合はoverrideキーワードを使用します。
public class SuperSample : Sample
{
public override void DoSample()
{
//Do Something.
}
public override string GetTitle()
{
return "タイトルだよ。";
}
}
「抽象」を言い換えると「具体的な実装を強制させる」というイメージであると言えると思います。「抽象」として定義されると、具体的な実装では「ないと困る処理」になるので、抽象で定義された処理がオーバーライドされてないとコンパイルエラーとなります。イメージとしては「【C#】インターフェースとは | インターフェースを使用する方法」で解説しているインターフェースに似ています。
抽象クラスのメリット
抽象クラスのメリットは、クラスの規約や雛形として活用されることが多く、大規模な開発において一定のルールとしてメリットがあります。例えば、何個かのファイル出力処理を数人で分担して作業する場合、指定のプロパティやメソッドを持たせることを強制できます。
それぞれが動くようにメソッドやプロパティを定義してしまうと、機能間の統一性がなく保守性が落ちてしまいます。そうしたことを防ぐために必要なクラスの要素を規約として強制させることができます。
抽象クラスは抽象メソッドを持つクラスですが、抽象メソッドは継承されたサブクラスから処理をオーバーライドして具体的な実装をコーディングしていきます。この辺りはインターフェースと近い感じです。
なお、インターフェースと同様に、抽象クラスのサブクラスにおいて抽象メソッドがオーバーライドされていないとコンパイルエラーとなります。
インターフェースは「機能」としてのクラスの要素を強制することができますが、抽象クラスでは「クラス」として要素を強制することができます。もちろん多重継承はできないので、サブクラスは必ず抽象クラスの規約を満たす必要があります。インターフェースは複数持つことができますが、抽象クラスでは一つだけなので大きな違いとなります。
抽象クラスは「分類」かつ「強制」
以上、オブジェクト指向においても重要といえる抽象クラスについて解説しました。
抽象クラスは様々なクラスを分類しつつ、かつ具体的な処理を強制することができるので、大規模な開発におけるルールやクラスの雛形として非常に有効な手段となります。抽象クラスを使用することでクラスをより設計書のような形式で扱うことが可能になります。
オブジェクト指向プログラミングにおいては、こうした「抽象」の世界でやり取りを考えることも重要になりますので、インターフェースと合わせて使い方をマスターしておくとよいと思います。またプログラマーでも「抽象」を扱える人は少ない印象なので、こうしたスキルを磨いておくと個人の評価も高まっていくと言えるでしょう。