前回は、クラスの基礎を行いました。今回は、クラスの継承です。

構造体までは、すんなり頭に入ったかもしれませんが、このへんから具体的に想像がしにくく、頭が混乱するかもしれません。ソフトウェアの学習は、パズルとパズルが繋がることで初めて「そういうことか!」と、気づくことがあります。
プログラミング入門時は、とりあえず色々やってまて、動きを知ることが習得の早道だと私は思っています。

クラスの継承とは、親クラス(ベースクラス、スーパークラス)の機能を受け継いだ子クラスを作ることができます。子クラスは、親クラスの変数・プロパティ・メソッドなどを引き継いでくれるため、同じコードを書かなくても済み、生産性が上がったりクラスのメンテナンスが容易になるなどのメリットがあります。

ここに来るまでに変数やオブジェクトを使ってみて最初から色々なメソッドが使えるから不思議に思われた方もいらっしゃるでしょう。クラスや構造体・列挙体は定義した時点でSystem.Objectクラスが継承されています。その為、ToStringやEqualsメソッドなどがいきなり使えたりします。

では、サンプルソースで継承の説明していきます。

C#

class Program
{
    /// 果物クラス
    public class Fruit
    {
        // ▼非公開メンバー変数
        private string m_name;
        // ▼継承クラスからはアクセス可能なメソッド
        protected int Tanka;
        // ▼どこからでもアクセスできるプロパティ
        public string Name { get { return this.m_name; } set { this.m_name = value; } }
        // ▼継承可能なメソッド
        public virtual string getSyurui()
        {
            return "なし";
        }
        // ▼親クラスのメソッド
        public decimal getKakaku(int kosu)
        {
            return (kosu * this.Tanka);
        }
        // ▼ Objectのメソッドをオーバーライド
        public override string ToString()
        {
            return string.Format("<<< 種類:{1}、果物の名前:{0} >>>", this.getSyurui(), this.Name);
        }

    }
    public class Apple : Fruit
    {
        // 子クラスのコンストラクタ
        public Apple(string name, int tanka)
        {
            this.Name = name;
            this.Tanka = tanka;
        }
        // 親クラスのメソッドをオーバーライド
        public override string getSyurui()
        {
            return "リンゴ";
        }
    }
    // エントリポイント
    static void Main(string[] args)
    {
        Apple a1 = new Apple("あまいリンゴ", 86);
        Apple a2 = new Apple("おいしいリンゴ", 105);
        OutMessage(a1);
        OutMessage(a2);
        Console.ReadLine();
    }
    // 出力メソッド
    static void OutMessage(Apple a)
    {
        Console.WriteLine(a.ToString());
        Console.WriteLine(a.Name + "は、10個でいくらですか?");
        Console.WriteLine("{0}円です。", a.getKakaku(10));
    }
}

出力結果

<<< 種類:あまいリンゴ、果物の名前:リンゴ >>>
あまいリンゴは、10個でいくらですか?
860円です。
<<< 種類:おいしいリンゴ、果物の名前:リンゴ >>>
おいしいリンゴは、10個でいくらですか?
1050円です。

Fruitという基底クラスを定義し、それを継承してるAppleクラスを作成しました。
Fruitクラスのメンバー変数m_nameは、privateなのでAppleクラスからアクセス(取得したり代入したり)できません。protected にしたTanka変数には、継承したクラスからアクセスが可能です。

FruitのgetSyuruiメソッド(関数)ですが、virtual修飾子がついています。これは、子クラスからこのメソッドの処理を置き換えて実装できるように宣言してあります。子クラスのAppleは、overrideをつけgetSyuruiメソッドの動作を実装しています。

もう一つのgetKakakuメソッドは、Appleクラスに何も記述しなくても、Appleクラスのインスタンス(実態)から呼び出しが可能となります。

FruitクラスもObjectクラスから継承されているので、virtualのToStringメソッドをオーバーライド(override)することができます。

Mainメソッドでは、2つのAppleクラスのインスタンスを作って結果を出力しています。
注目して頂きたいところが2つあります。
1つ目は、OutMessageメソッド内で、親クラスのオーバーライドされたToStringです。getSyuruiメソッドが子クラスでオーバーライドした側が呼ばれているところです。
2つ目のgetKakakuメソッドも親クラスのメソッドを使って計算していることも確認できました。

小走りに色々と説明していきましたが、オブジェクト指向プログラミングは奥が深いので、今後もクラスなどについて書いていければと思います。