最初のプログラム言語はJavaでした。インスタンスやクラス、インターフェースや抽象クラス、キャストなど色々な横文字が大量に出てきて何が何やらわからず、苦労した思い出があります。
ある時なんとなくJavaが理解できた時の思い出です。
インスタンスとは
クラスをnew するとインスタンス(実体)になります。インスタンスは常にどのクラスのインスタンスなのかを持っています。例としてBigDecimalを使います。
コードで書くと次になります。
new BigDecimal(100);
new BigDecimal(200);
変数とは
Javaでは、継承:extends と実装: implements の仕組みがあります。
その仕組みの中で"インスタンスの参照"を格納できる変数の型に制限があります。
その制限は、インスタンスのクラスの定義で、自身のクラス以上が継承したクラスや、自身のクラス以上が実装したインタフェースのみインスタンスの参照を保持できるというものです。
BigDecimalが継承したクラスと実装したインタフェースは次の通りで、次のクラスとインタフェースがBigDecimalのインスタンスを格納できます。
クラスから作成したインスタンスを格納できる変数の関係は次の通りです。
コードにすると次になります。
BigDecimal decimal100 = new BigDecimal(100);
Object obj100 = decimal100;
Number num100 = decimal100;
Serializable sel100 = decimal100;
Comparable com100 = decimal100;
BigDecimal decimal200 = new BigDecimal(200);
Object obj200 = decimal200;
Number num200 = decimal200;
Serializable sel200 = decimal200;
Comparable com200 = decimal200;
サンプルとしてNumber型の変数num100を例にするとnum100に格納されているのは、BigDecimalクラスのインスタンスなので、キャストをすればBigDecimal型に格納し直すこともできます。
BigDecimal decimal100_c = (BigDecimal)num100;
抽象クラス
いまいちインターフェースとの使い分けがわからなかったのですが、抽象クラスは実装メソッドが持てて、そのメソッドの中で抽象メソッドも使えるというのが理解できてなんとなく使い方がわかりました。
public abstract class AbstractSample {
protected void start(){
}
//抽象メソッド
abstract protected void execute();
protected void end(){
}
//メソッド内で、抽象メソッドを使っておく。
public void process(){
start();
execute();
end();
}
}
共通の部分はabstarct クラス側で実装しておいて、個別の処理はextendしたクラス側で実装を強制させることができます。似たような処理をクラスを分けて実現する場合、きれいに書けると思います。(現実は、1つのメソッドの中で分岐で実現することがほとんどだと思いますが。。)
終わりに
Webのフレームワークや、Javaのクライアント側のSwingなどは、抽象クラス、インタフェースを書いて覚えるにはちょうど良いと思います。
あまりやりすぎた継承や実装は好きではないですが、ちょっと工夫することで効率が大きく変わるのでオブジェクト指向は楽しいと思いました。