C#入門(第12回)

前回振り返り

抽象クラスとは

抽象クラスは抽象メソッドを一つ以上持っているクラスとして定義されます。C#では「抽象」をabstractキーワードで表現しており、具体的な実装を持っていません。先に学習したインターフェースに近く、継承したクラスに対し、実装を強制します。抽象クラスは以下のような感じで定義されます。

public abstract class AbstractSample
{
    public int Id { get; }
    
    public abstract void hoge();
    public abstract string hogehoge();
}

上記のようにabstractで定義されたクラスには、abstractで定義されているメソッドが一つ以上必要となります。abstractメソッドには具体的な実装は記載せず、あくまでもメソッドとしての呼出口だけの定義を行います。通常のプロパティ・メソッドも普段通りに記載することが可能です。

抽象メソッドを継承したスーパークラスでは、インターフェースの時と同様に抽象メソッドとして定義された処理の具象部分を定義しなくてはなりません。スーパークラスとして以下のようになります。スーパークラスにおいて具体的な実装をコーディングする場合は、overrideキーワードを使用します。

public class Sample : AbstractSample
{
    public override void hoge()
    {
        //実装
    }

    public override string hogehoge()
    {
        //実装
    }
}

抽象クラスのメリット

抽象クラスのメリットは、クラスの規約や雛形として活用されることが多く、大規模な開発において一定のルールとしてメリットがあります。例えば、何個かのファイル出力処理を数人で分担して作業する場合、指定のプロパティやメソッドを持たせることを強制できます。それぞれが動くようにメソッドやプロパティを定義してしまうと、機能間の統一性がなく保守性が落ちてしまいます。そうしたことを防ぐために必要なクラスの要素を規約として強制させることができます。

抽象クラスは抽象メソッドを持つクラスですが、抽象メソッドは継承されたサブクラスから処理をオーバーライドして具体的な実装をコーディングしていきます。この辺りはインターフェースと近い感じです。なお、インターフェースと同様に、抽象クラスのサブクラスにおいて抽象メソッドがオーバーライドされていないとコンパイルエラーとなります。

インターフェースは「機能」としてのクラスの要素を強制することができますが、抽象クラスでは「クラス」として要素を強制することができます。もちろん多重継承はできないので、サブクラスは必ず抽象クラスの規約を満たす必要があります。インターフェースは複数持つことができますが、抽象クラスでは一つだけなので大きな違いとなります。

抽象クラスは「分類」かつ「強制」

以上、オブジェクト指向においても重要といえる抽象クラスについて解説しました。抽象クラスは様々なクラスを分類しつつ、かつ具体的な処理を強制することができるので、大規模な開発におけるルールやクラスの雛形として非常に有効な手段となります。抽象クラスを使用することでクラスをより設計書のような形式で扱うことが可能になります。

オブジェクト指向プログラミングにおいては、こうした「抽象」の世界でやり取りを考えることも重要になりますので、インターフェースと合わせて使い方をマスターしておくとよいと思います。またプログラマーでも「抽象」を扱える人は少ない印象なので、こうしたスキルを磨いておくと個人の評価も高まっていくと言えるでしょう。

前回演習問題の解答 例

問題1

問題文

抽象クラスを作成してみましょう。


解答例

    abstract class Fruit
    {
        public abstract void peel();

        public void eat()
        {
            peel(); // 皮をむく
            Console.WriteLine("食べる");
        }

    }

問題2

問題文

抽象クラスを継承したクラスを3つ作成してみましょう。


解答例

    class Apple : Fruit
    {

        public override void peel()
        {
            Console.WriteLine("リンゴの皮をむきます");
        }
    }

    class Cherry : Fruit
    {
        public override void peel()
        {
            Console.WriteLine("皮が無いので何もしない");
        }
    }

    class Strawberry : Fruit
    {
        public override void peel()
        {
            Console.WriteLine("皮が無いので何もしない");
        }
    }

今回の演習問題

問題1

問題文

Strategy パターン をインターフェースを使って作成してみましょう。

問題2

問題文

Strategy パターン を継承関係を必要としないデリゲートを使って作成してみましょう。

コメント