frei

旧「anney's room」からブログ「frei」だけ引っ越し&残しました

悩ましきポリモーフィズム。

昨日は学校デー。

英会話に行ってから、その後Java学校へ。

一気に疲れる日ですな。

てな訳で、久々に「堂々として」ビールを飲みつつ

Java学校を振り返ってメモっときます(笑)

さて、メインテーマは、

ポリモーフィズムカプセル化でした。

今回は説明が長くなっちゃうんで、

ポリモーフィズムだけメモります。

ポリモーフィズム

呼び出すメソッド名は同じなのに

振る舞いが違う状態のこと。

perlPHPでは 正直使った事ないんで、

ようわからんのですが(笑)

どっちも実装できるらしいです。

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();

…として使う事も出来るそうな。

スーパークラスの型に、継承クラスでオブジェクト化???

・・・・・なんだこりゃ(汗)

雰囲気的に、

スーパークラス内のメンバ変数やメソッドは動きそうだけど、

継承クラス内のメンバ変数やメソッド

一体どうなっちゃうのさ?

せっかく、スーパークラス内のtestMethodメソッド

継承クラス内で、オーバーライドもしたってーのにさぁ。

危うし、継承クラス!

どうなる継承クラスーーーっ!

…と思ったら(^^;

継承クラス内のメンバ変数やメソッド

外部から参照したり呼び出す事ができなくなるんだけど

水面下では、ちゃんと存在しているそうな。

あら、ちゃんといたんだ。継承クラス。

でも、水面下で存在してても、

外部から使えないメンバ変数とメソッドって

何も意味がないんじゃ?

…と思ってたら(^^;;

スーパークラス内のメソッド

継承クラスでオーバーライドされた物だけは

外部から実行できるんだってさ。

なんてやねん。

そういう訳で(^^;;;;;

上記の例で言うと…

 SuperClassTest test = new SubClassTest();

…で、インスタンス化された、test参照変数を用いて…

  test.testMethod();

…と、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なんどすえ

なるほどねぇ…。確かに便利だわ。

今のところ、使うあてが思い浮かばないけど(^^;