D言語/オブジェクト指向

出典: フリー教科書『ウィキブックス(Wikibooks)』

D言語は、C++やJavaと同様に、オブジェクト指向プログラミングをサポートしています。 オブジェクト指向プログラミングは、プログラムの構造をオブジェクト(実体)として定義し、オブジェクト同士の相互作用によってプログラムを構築する方法です。 この章では、D言語におけるオブジェクト指向プログラミングの基礎から具体的な実装方法まで解説します。 具体的には、クラスやオブジェクトの定義方法、継承やポリモーフィズムといったオブジェクト指向の重要な概念について説明します。 また、D言語のオブジェクト指向プログラミングにおける特徴や、他のオブジェクト指向言語との比較についても触れます。

この章を読むことで、D言語におけるオブジェクト指向プログラミングの基礎を身につけ、より効率的で柔軟性の高いプログラムを作成することができるようになるでしょう。

クラス[編集]

クラスは複数の変数を一まとめにし、それらを扱う関数も内包することで、簡潔で他のプログラムに依存しない独立した処理を可能とします。また、クラスは雛形であり、同じ性質を持ったデータ(オブジェクト)を多数作ることができます。

実体化[編集]

クラスは雛形に過ぎないため、実際に変数として使うためには、定義や宣言した後に実体化(インスタンス化)する必要があります。例えば、クラスCのオブジェクトc1を宣言するには、以下のように実体化します。

C c1;    // 宣言
c1 = new C();

newはオブジェクトをヒープにアロケートする演算子であり、その対象はCというクラスです。空白の()は後述するコンストラクタに何も指定しないことを意味します。


メンバ変数[編集]

クラスの中に定義された変数を特にメンバ変数と言います。 オブジェクトの持つデータそのもので、これを扱いやすくするための仕組みが以下のようになります。

メンバ関数(メソッド)[編集]

クラスの中に定義された関数を特にメンバ関数、メソッドと言います。 メンバ変数に対する決まりきった処理を他のオブジェクトに依存すると、関わるオブジェクト数が増えるため、複雑で読みにくく、直しにくいコードになります。メンバ変数の処理はメンバ関数に任せましょう。

コンストラクタ[編集]

this() という名前を持つ特殊なメンバ関数で、クラスをオブジェクトとして実体化する際に、this() 関数の中で定義された初期化処理を実行します。引数なしの場合はメンバ変数のデフォルト値を与えるのに使います。初期化するだけなので、返り値はありません。

this()
{
    i = 0;
    str = "Default string";
}

引数ありの場合も定義でき、何個でも定義できます(オーバーライド)

this(int x)
{
    i = x;
    str = "int override";
}
this(string strin)
{
    i = 0;
    str = strin;
}

ここで定義した関数は、new実行時にC(引数)と表記する事で、引数に応じてthis(引数)関数を実行します。様々な初期状態を持った同じクラスのオブジェクトを作るのに便利です。

演算子オーバーロード[編集]

四則演算(+-*/)など多くの演算記号を、クラスに対してまるごと作用させる演算を定義できます。

インターフェース[編集]

インターフェースというものによってメソッドの実装を強制することができます。

interface Bell {
    void ring(int sec);
}

class AlarmClock : Bell {
    void ring(int sec) {
        import std.stdio: writeln;
        while(sec > 0) {
            writeln("Good Morning!");
            --sec;
        }
    } 
}

void main(){   
    auto my_clock = new AlarmClock();
    my_clock.ring(10);

}
実行結果
Good Morning!
Good Morning!
Good Morning!
Good Morning!
Good Morning!
Good Morning!
Good Morning!
Good Morning!
Good Morning!
Good Morning!
解説

インターフェースはクラスの持つべきメソッドのリストであり、そのインターフェースを継承したらすべてのメソッドを実装しなければならない。つまり、インターフェースは、それらのメソッドを持つ型の定義なのである。

備考

インターフェース内のメソッドにin-out契約を指定することもできる[1]


C++とDとのオブジェクト指向の差異[編集]

D言語とC++は両方ともオブジェクト指向言語ですが、いくつかの重要な差異があります。

  1. クラス定義のシンタックス:D言語では、クラス定義はstructキーワードまたはclassキーワードを使用して行われます。C++とは異なり、structは値型、classは参照型とです。
  2. プライベートなメンバー:C++では、privateキーワードを使用してクラスの非公開メンバーを定義します。D言語では、privateキーワードはクラス定義にも使用されますが、メンバー変数には、アクセス指定子が指定されていない場合にプライベートになります。
  3. コンストラクターとデストラクター:D言語では、クラスのコンストラクタとデストラクタはそれぞれthis()と~ this()という名前で定義されます。C++では、コンストラクタはクラス名と同じ名前で、デストラクタはクラス名の前に波線(~)を付けて定義します。
  4. 継承:D言語では、クラス継承には2つの異なるキーワードがあります。is-a関係を表す場合にはclassキーワードを使用し、has-a関係を表す場合にはinterfaceキーワードを使用します。class型はObjectを暗黙的に継承します。C++では、派生クラスの定義には、単一継承または多重継承を示すキーワードが使用されます。
  5. GC:D言語では、ガベージコレクションが標準でサポートされています。これにより、C++のようなメモリ管理が必要なくなります。C++では、手動でメモリを確保し、解放する必要があります。
  6. プロパティ:D言語では、プロパティと呼ばれる独自の機能を使用して、クラスのメンバー変数のアクセスを制御することができます。C++には、同様の機能がありません。

以上が、D言語とC++のオブジェクト指向の主な差異です。

  1. ^ Interfaces - D Programming Language 2020年7月20日に閲覧して確認