【C#】オブジェクト指向(継承とは)

継承とは

C#でオブジェクト指向設計する上で代表的なものとして、「カプセル化」「インターフェース」「継承」の3つがあります。

継承とは、あるクラスのメンバ(フィールドやメソッド)を他のクラスに引き継ぐ機能のことです。

例えば、「クラスA」で計算するロジックを作ったとします。
このクラスAの計算するロジックを「クラスB」でも使用したい時に継承を用いることでクラスBでも計算するロジックを使用することが可能となります。

 

継承のメリット

継承のメリット①:コード量の削減

継承を用いることで、コード量を減らすことができます。

 

継承のメリット②:View(画面)の統一

継承は、ロジックだけでなくコントロールやフォーム(画面)も継承することができます。

アプリケーションに1つ、基底となるコントロールやフォームを作成し、それを継承することで統一されたView(画面)を作成することが可能となります。

 

継承のデメリット

コードが読みづらくなる

継承を使いすぎて、可読性の悪いコードがあると保守性が低下します。
可読性の悪いコードはカスタマイズや機能追加の際、コードを追っていくことが大変です。
実際の開発現場においても継承が多用されており、カスタマイズや機能追加の際にコードを追いかけることに大変時間を割かれてしまうことがあります。

このように、継承は非常に便利な機能ではあるものの、使いどころによっては逆に可読性の悪いコードを生むことになります。

継承を使用するか際には、まず「抽象クラス」もしくは「インターフェース」での実装を試みて、どうしても必要な場合のみ「継承」を使うことが望ましいかと思います。

 

継承の使い方

class サブクラス名 : ベースクラス名
{
}

継承を実装するには、「class サブクラス(派生クラス)名 : ベースクラス(基底クラス)名」と記述します。

基底クラスのコンストラクタに値を渡したい時には、「サブクラスのコンストラクタ名 : base(引数)」と記述します。

C#は単一継承

C#では、1つのクラスから何個でもサブクラスを作ることは可能です。
しかし、サブクラス1つに対してベースクラスは1つしか存在しません。

このように、ベースクラスが1つしかない継承の仕方を「単一継承」といいます。

他のプログラミング言語によっては、1つのクラスに複数のベースクラスを設定することができます。
これを「多重継承」といいます。

ただし、C#でも「継承の継承」のような使い方は可能です。
実際の開発現場においても、「継承した先がまた違うクラスを継承している」なんてことも多々あります。
しかし、可読性においては非常に悪いコードになってしまうため、このような使い方は避けましょう。

 

サンプルコード

using System;

namespace inheritance
{
    class Program //  ベースクラス
    {
        string _name;
        int _number;

        public Program(string name, int number) // ベースクラスのコンストラクタ
        {
            _name = name;
            _number = number;
            Console.WriteLine("ベースクラス");
            Console.WriteLine("商品名:" + name + ", 個数:" + number);
            Console.WriteLine("------------");
        }

    }

    class Program1 : Program
    {
        int _id;
        string _customer;

        public Program1(string name, int number, int id, string customer) : base(name, number) //  サブクラスのコンストラクタ
        {
            _id = id;
            _customer = customer;
            Console.WriteLine("サブクラス");
            Console.WriteLine("顧客番号:" + id + ", 顧客名:" + customer);
        }

        static void Main(string[] args)
        {
            Program1 program1 = new Program1("せんべい", 2, 2260, "田中太郎"); // インスタンス生成
        }
    }
}

 

実行結果:
ベースクラス
商品名:せんべい, 個数:2
————
サブクラス
顧客番号:2260, 顧客名:田中太郎

上記のように、ベースクラスのコンストラクタに値を渡したい時には、「サブクラスのコンストラクタ名 : base(引数)」と記述します。

 

継承されたくない時はsealed

継承されたくないクラスがある場合には、「sealed」を使います。

public sealed class AAA
{
}

上記のように、クラスを宣言する際に「sealed」を記述することで継承されることを防ぎます。

クラスを作る際には、基本的に「sealed」をつけると良いと思います。
そして、継承するときにだけ「sealed」を外すといった実装方法が可読性・保守性を高く保つことにつながっていきます。

 

おすすめ・参考書籍

■C#を学習し始めた方向け
やさしいC 第3版 (「やさしい」シリーズ)

1週間でCの基礎が学べる本

確かな力が身につくC「超」入門 第2版 (Informatics&IDEA)

■C#をある程度学習した方向け
基礎からしっかり学ぶCの教科書 改訂新版 (マイクロソフト関連書)

独習C 新版

Effective C 6.0/7.0

オブジェクト指向における再利用のためのデザインパターン