悩ましきポリモーフィズム。
昨日は学校デー。
英会話に行ってから、その後Java学校へ。
一気に疲れる日ですな。
てな訳で、久々に「堂々として」ビールを飲みつつ
Java学校を振り返ってメモっときます(笑)
さて、メインテーマは、
今回は説明が長くなっちゃうんで、
ポリモーフィズムだけメモります。
呼び出すメソッド名は同じなのに
振る舞いが違う状態のこと。
ようわからんのですが(笑)
どっちも実装できるらしいです。
※PHPは ver.5から
- 「メソッド名が同じなのに振る舞いが違う」状態とは?
前回習ったインターフェースや抽象クラスで使った
抽象メソッドを継承したクラスがいくつかある事で
「同じ名前なのに実装内容が違う」メソッドが
クラス毎にある事になる模様。
例)
// インターフェース
public interface TestInterface {
public void open(); // 抽象メソッド
}
// 継承クラス1
public class TestClass1 implements TestInterface {
public void open() {
// TestClass1内でのopenを実装
System.out.println( "こちらはTestClass1でっせ" );
}
}
// 継承クラス2
public class TestClass2 implements TestInterface {
public void open() {
// TestClass2内でのopenを実装
System.out.println( "こちらはTestClass2なんどすえ" );
}
}
// 実行クラス内
public static void main( Strings[] args ) {
TestClass1 test1 = new TestClass1(); // インスタンス化
TestClass2 test2 = new TestClass2(); // インスタンス化
test1.open(); // TestClass1のopenを実行
test2.open(); // TestClass2のopenを実行
// ↑2つともメソッド名が同じなのに振る舞いが違う
}
-「メソッド名が同じなのに振る舞いが違う」と何が便利なのか?
同じ抽象メソッドを継承しているクラスなら、
同じメソッド名で、実行が可能。
だから、いちいちそれぞれのクラスにあわせた
メソッド名を覚えなくてもOK!
- 不思議な動きの動的束縛
Javaだけの特性なんだか、
不思議な動きがある事を知りました(^^;
例)
// スーパークラス
public class SuperClassTest {
int SID;
public void testMethod() {
// SuperClassTest内でのtestMethod
System.out.println( "こちらはSuperClassTestのtestMethodです" );
}
}
// 継承クラス
public class SubClassTest extends SuperClassTest {
int age;
String name;
public void testMethod() {
// ↓SuperClassTest.testMethodのオーバーライド
// SubClassTest内でのtestMethod
System.out.println( "こちらはSubClassTestのtestMethodです" );
}
}
こんなクラス達がいたとして
普通、継承クラスTestをインスタンス化するには…
SubClassTest test = new SubClassTest();
…とするところですが、
自分より上のクラスをデータ型の所に設定する事が出来るそうで、
SuperClassTest test = new SubClassTest();
…として使う事も出来るそうな。
スーパークラスの型に、継承クラスでオブジェクト化???
・・・・・なんだこりゃ(汗)
雰囲気的に、
継承クラス内のメンバ変数やメソッドは
一体どうなっちゃうのさ?
継承クラス内で、オーバーライドもしたってーのにさぁ。
危うし、継承クラス!
どうなる継承クラスーーーっ!
…と思ったら(^^;
継承クラス内のメンバ変数やメソッドは
外部から参照したり呼び出す事ができなくなるんだけど
水面下では、ちゃんと存在しているそうな。
あら、ちゃんといたんだ。継承クラス。
でも、水面下で存在してても、
外部から使えないメンバ変数とメソッドって
何も意味がないんじゃ?
…と思ってたら(^^;;
継承クラスでオーバーライドされた物だけは
外部から実行できるんだってさ。
なんてやねん。
そういう訳で(^^;;;;;
上記の例で言うと…
SuperClassTest test = new SubClassTest();
…で、インスタンス化された、test参照変数を用いて…
test.testMethod();
…と、testMethodメソッドを呼び出すと
唐突に継承クラスTest内のtestMethodが実行されるそうです。。。
これをふまえて。
さっきのインターフェースを
ちょいと書き足して持ってきまして…
例)
// インターフェース
public interface TestInterface {
public void open(); // 抽象メソッド
public void exec(); // 抽象メソッド
public void close(); // 抽象メソッド
}
// 継承クラス1
public class TestClass1 implements TestInterface {
public void open() {
// TestClass1内でのopenを実装
System.out.println( "こちらはTestClass1のopenでっせ" );
}
public void exec() {
// TestClass1内でのexecを実装
System.out.println( "こちらはTestClass1のexecでっせ" );
}
public void close() {
// TestClass1内でのcloseを実装
System.out.println( "こちらはTestClass1のcloseでっせ" );
}
}
// 継承クラス2
public class TestClass2 implements TestInterface {
public void open() {
// TestClass2内でのopenを実装
System.out.println( "こちらはTestClass2のopenなんどすえ" );
}
public void exec() {
// TestClass2内でのexecを実装
System.out.println( "こちらはTestClass2のexecなんどすえ" );
}
public void close() {
// TestClass2内でのcloseを実装
System.out.println( "こちらはTestClass2のcloseなんどすえ" );
}
}
…という状態で、
両継承クラスのメソッドを次々に実行したい場合、
それぞれのメソッドを、コツコツ書いていくと面倒なんで
以下のように書けるのだそうな。
// 実行クラス内
public static void method( TestInterface obj ) {
obj.open();
obj.exec();
obj.close();
}
public static void main( Strings[] args ) {
TestInterface obj = {
new TestClass1(), // インスタンス化
new TestClass2() // インスタンス化
};
for ( int num = 0; num < obj.length; num++ ) {
method( obj[num] );
}
}
結果)
こちらはTestClass1のopenでっせ
こちらはTestClass1のexecでっせ
こちらはTestClass1のcloseでっせ
こちらはTestClass2のopenなんどすえ
こちらはTestClass2のexecなんどすえ
こちらはTestClass2のcloseなんどすえ
なるほどねぇ…。確かに便利だわ。
今のところ、使うあてが思い浮かばないけど(^^;