カプセル化という意味で考えた場合のinterface。


キーストン ホーム

前に戻る

カプセル化という意味で考えた場合のinterface。

「エギンガーがエギシャープでアオリイカを釣る」という動作をオブジェクト化してみる。

使うのは以下の3つのクラスである。

Egingerクラス
Squidクラス
Egiクラス

エギンガーオブジェクトが、釣れたイカオブジェクトをインスタンス変数として保持する。

------------------------------------------------------------------------------------------
class Eginger
{
    private Squid squid = null;

    public Eginger(String aName)
    {
        this.name=aName;
    }

    //初期化なしのコンストラクタは許可しない
    private Eginger()
    {
    }

    // Squid クラスのpublicメソッドを全部利用できる。
    public void fishOnSquid(Squid aSquid)
    {
        this.squid=aSquid;
    }
}

class Squid
{
    public Squid(String aName, double aSize, int aAge)
    {
        this.name=aName;
        this.size=size;
        this.age=aAge;
    }

    //初期化なしのコンストラクタは許可しない
    private Squid()
    {
    }
}

------------------------------------------------------------------------------------------
ということは、この設計だと、エギンガーはイカのあらゆる情報を取り出すことが出来る。
となると、イカの個人情報(この場合、年齢)までも取得が可能だ。

イカが年齢を知られたくないかどうかは定かでないが、きっと「えっ?その年齢でその体格?」と
にっくきエギンガーに思われたくないに違いない。(must be!!)
(細かい話をすると、イカは年齢じゃなくて、月齢ですね。)

そうなると、クラス設計時に知られたくない情報をprivateメソッドにすれば良い話だが、
イカも結婚するときには年齢を提示しなくてはならない(!?)わけだから、publicである必要がある。
だけど、なるべく不必要な情報は知られたくない。

こういう場合に、interface を用いる。まさにインターフェースなわけで、必要な情報だけ
わたすことが出来る。つまり、エギンガーに自分の年齢を知られなくて済むわけだ。


------------------------------------------------------------------------------------------
interface Isquid
{
    public String getName();
    public double getSize();
}

class Eginger
{
    private Isquid squid = null;

    public Eginger(String aName)
    {
        this.name=aName;
    }

    //初期化なしのコンストラクタは許可しない
    private Eginger()
    {
    }

    // Isquid クラスのpublicメソッドのみ利用できる。
    // つまりgetNameとgetSizeメソッドのみ利用できる。
    public void fishOnSquid(Isquid aSquid)
    {
        this.squid=aSquid;
    }
}
------------------------------------------------------------------------------------------

重要な話だが、基本的にダウンキャストは駄目である。元も子もない。
名著 Effective C++ によると、ダウンキャストを避けるように設計すべき、とある。
そのとおりである。(だけどjavaってダウンキャスト普通に使わないと駄目よね。)

しっかり設計しないと、カプセル化をしているわけだから、がんじがらめになって、
酷いソースコードになる場合もあるから注意が必要だ。わたしは以前がんじがらめになったあげく、
static な変数とメソッドをたくさん用意して、とっても恥ずかしいソースコードを作った経験がある。
sitaticな変数はグローバル変数的性質を持たせると、悪となる。

ちなみに、C++では、純粋仮想関数を定義したクラスが、いわゆるJavaのinterfaceと同じような機能だ。

------------------------------------------------------------------------------------------
#include <iostream>

class ISquid
{
    public:
        virtual char* getName() = 0;
        virtual double getSize() = 0;
};

------------------------------------------------------------------------------------------


rubyには型がないので、C++やJavaの場合とは違う脳みそを使う。
(ruby脳で設計する。ちなみにlisp脳とか、haskell脳とかもあるに違いない。独り言。)

イカはとっても恥ずかしがり屋なのである。

前に戻る