JPIN#10
復習(ポリモーフィズム)
クラスは以下のように表現できる
クラス=型(扱い方)+実装(処理)
クラスAがあったとする
「クラスAは「できること(目録)」+「実際の動作」でできている
クライアントにとってはこのクラスAのできることが重要であるので実際の動作がどう変わろうがクライアントにとっては別にいいのである
これがポリモーフィズムである
インターフェイス
ルールや規約を示すものである
型だけを定義したものである
public interface A { public void hello(); }
上記のように型情報だけのものであり、それを抽象メソッドという
これは中身がない
メソッドはあるが処理内容がないものである
これをインターフェイスというものを使ってあらゆるクラスで使用することができる
public class B implements A{ @Override public void hello() { System.out.println("B"); } }
Aのインターフェイスを使用するにはimplements(実装という意味)で使用することができる
これをすることによってAのインターフェイスを継承しているのでhelloメソッドを必ず使わなければならない
public class D implements A { }
上記のようなDクラスではインターフェイスのメソッドを使用していないのでコンパイルエラーになる
インターフェイスを使うときは必ず型にあるものを全てオーバーライドしないとならない
こうすることによって間違った使われ方を防ぐ役目がある(情報隠蔽)
インターフェイスではメソッドと定数しか使用することができない
またインターフェイスとインターフェイスは継承することができる
public interface AA { public void hoge(); }
上記のBクラスがあったとする
これとAのインターフェイスを複合して使いたい場合は継承すれば良い
public interface A extends AA{ public void hello(); }
このようなインターフェイスを用意した場合、使用クラスは両方の要素を使わなければならない
その場合は下記のようになる
public class B implements A{ @Override public void hello() { System.out.println("B"); } @Override public void hoge() { System.out.println("hoge"); } }
抽象クラス
インターフェイスを使っているクラスを継承するときは継承先のクラスでももちろんインターフェイスの全てのメソッドを使用しなければならない
この時に継承されるクラスには特に動かす必要はなく、継承先で動くようにしたい場合は継承されるクラスの中身は空でいい
このようなクラスを抽象クラスという
このクラスはインターフェイスから型を受け取っていて、さらに継承先のクラスの共通部分の型も持っているものである
抽象クラスはインターフェイスと実装継承の両方の性質を持つクラスである
この抽象クラスはインスタンスすることはできない(する必要もない)
public interface A { public void hello(); public void bye(); }
上記のAインターフェイスがあるとする
これを使う抽象クラスをEとする
public abstract class E implements A{ @Override public void bye() { System.out.println("bye"); } }
ここではbyeメソッドをオーバーライドしたがabstractで抽象クラスとなっているのでメソッドを書かなくても良い
次にこれを継承するクラスBを定義する
public class B extends E{ public void hello() { System.out.println("B"); } }
BクラスではAのインターフェイスで定義されたメソッドのうちEで何もオーバーライドされていないものを書かなければならない
ここではhelloメソッドを定義している
これによってBクラスはコンパイルエラーが出ない
これを使いたいときはEかBのインスタンスを生成することができる
Mainメソッドでは以下のようになる
public class Sample { public static void main(String[] args) { // TODO Auto-generated method stub A a = new B(); a.hello(); a.bye(); B b = (B) a; //ダウンキャスト b.test(); } }
Eクラスにサブクラスの共通部分を作りたい場合は次のように書く
public abstract class E implements A{ @Override public void bye() { System.out.println("bye"); } public abstract void test(); }
追加したいメソッドにabstractを加えて宣言する
これでtestメソッドは抽象化できる
これをBクラスで使用しなければならないのでBクラスは以下のようになる
public class B extends E{ public void hello() { System.out.println("B"); } public void test() { System.out.println("test"); } }
これでtestメソッドも使用できるようになる
しかしこのtestメソッドはBクラスでEクラスで作られたものなので型宣言する場合はEで宣言する必要がある
または、ダウンキャストという方法で使うことができるようになる
今まで親クラスの型で宣言してサブクラスを使用していた
これをアップキャストという
この逆をダウンキャストという
public class Sample { public static void main(String[] args) { // TODO Auto-generated method stub A a = new B(); a.hello(); a.bye(); B b = (B) a; //ダウンキャスト b.test(); } }
このようにB型のbにA型のaを代入することができる