カプセル化という意味で考えた場合の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脳とかもあるに違いない。独り言。)
イカはとっても恥ずかしがり屋なのである。
前に戻る