#pragma twice

KAB-studio > プログラミング > Javaのオブジェクト指向入門 > 7. ポリモーフィズム!! > 7.3 オーバーライドされたメソッドを呼び出すと?再び
 
前のページへつぎ

7.3 オーバーライドされたメソッドを呼び出すと?再び

del.icio.us 登録する はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数 livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数 Yahoo!ブックマーク 詳細を表示 users RSSに登録
更新日: 2008/04/14
動作確認環境:Windows XP Professional SP2, Java SE 5

オーバーライドされたメソッドを呼び出す

 前ページでは、アップキャストをすることで「使えるフィールド・メソッドがスーパークラスのものに限られる」ということを説明しました。
 この状態で、スーパークラスの「オーバーライドされたメソッド」を呼び出すと、面白いことが起きます。

// OverridedSub4Runner.java

/**
 * 普通のクラス。
 * メソッド1つ持ちます。
 * (HasOneMethodSuperクラスと全く同じです)
 */
class HasOneMethodSuper4
{
    /**
     * 自クラスの名前を出力するメソッドです。
     */
    void printMyName()
    {
        System.out.println( "HasOneMethodSuper4" );
    }
}

/**
 * HasOneMethodSuper4クラスから継承した、サブクラス。
 * メソッドを追加しています。
 * (OverridedSubクラスと全く同じです)
 */
class OverridedSub4 extends HasOneMethodSuper4
{
    /**
     * 自クラスの名前を出力するメソッドです。
     * オーバーライドしています。
     */
    void printMyName()
    {
        System.out.println( "OverridedSub4" );
    }
}

/**
 * 実行用クラス。このクラスを実行してください。
 */
class OverridedSub4Runner
{
    public static void main( String[] args )
    {
        // インスタンスを1つ作ります。
        // ただし、参照型変数の型はスーパークラスです。
        HasOneMethodSuper4 refSuper = new OverridedSub4();

        // printMyName()メソッドを呼び出します。
        refSuper.printMyName();
        // 出力結果:
        // OverridedSub4
    }
}
// OverridedSub4Runner.java
/**
 * 普通のクラス。
 * メソッド1つ持ちます。
 * (HasOneMethodSuperクラスと全く同じです)
 */
class HasOneMethodSuper4
{
	/**
	 * 自クラスの名前を出力するメソッドです。
	 */
	void printMyName()
	{
		System.out.println( "HasOneMethodSuper4" );
	}
}
/**
 * HasOneMethodSuper4クラスから継承した、サブクラス。
 * メソッドを追加しています。
 * (OverridedSubクラスと全く同じです)
 */
class OverridedSub4 extends HasOneMethodSuper4
{
	/**
	 * 自クラスの名前を出力するメソッドです。
	 * オーバーライドしています。
	 */
	void printMyName()
	{
		System.out.println( "OverridedSub4" );
	}
}
/**
 * 実行用クラス。このクラスを実行してください。
 */
class OverridedSub4Runner
{
	public static void main( String[] args )
	{
		// インスタンスを1つ作ります。
		// ただし、参照型変数の型はスーパークラスです。
		HasOneMethodSuper4 refSuper = new OverridedSub4();
		// printMyName()メソッドを呼び出します。
		refSuper.printMyName();
		// 出力結果:
		// OverridedSub4
	}
}

 このプログラムは「5.3 オーバーライドで「上書き」する」に似たプログラムです。
 HasOneMethodSuper4クラスとOverridedSub4クラスはその時のものと全く同じで、クラス名が違うだけです。
 継承関係も同じで、HasOneMethodSuper4クラスからOverridedSub4クラスに継承しています。HasOneMethodSuper4クラスがスーパークラス、OverridedSub4クラスとなります。
 また、HasOneMethodSuper4クラスのprintMyName()メソッドをOverridedSub4クラスでオーバーライドしています。

 インスタンスの作成箇所は少し違います。
 参照型変数の型をスーパークラスのHasOneMethodSuper4クラスにして、アップキャストして受け取っています。

        // インスタンスを1つ作ります。
        // ただし、参照型変数の型はスーパークラスです。
        HasOneMethodSuper4 refSuper = new OverridedSub4();
		// インスタンスを1つ作ります。
		// ただし、参照型変数の型はスーパークラスです。
		HasOneMethodSuper4 refSuper = new OverridedSub4();

 インスタンスはOverridedSub4クラス型なので、中にHasOneMethodSuper4クラスのインスタンスも作られ、オーバーライドしているprintMyName()メソッドが結びつけられます。

 このrefSuper変数の型はHasOneMethodSuper4クラスですので、HasOneMethodSuper4クラスのフィールド・メソッドのみ使用できます。
サブクラスであるOverridedSub4クラスのフィールド・メソッドは使えません。

 さてでは、refSuper変数を通して、printMyName()メソッドを呼び出すと、どうなるのでしょう。
 printMyName()メソッドはオーバーライドしているわけですから、スーパークラスにもサブクラスにもあります。
 refSuper変数はスーパークラスの参照型変数ですから、当然スーパークラスのprintMyName()メソッドが呼び出される……と思いきや、実はサブクラスの、オーバーライドしたメソッドが呼び出されます

        // printMyName()メソッドを呼び出します。
        refSuper.printMyName();
        // 出力結果:
        // OverridedSub4
		// printMyName()メソッドを呼び出します。
		refSuper.printMyName();
		// 出力結果:
		// OverridedSub4

 この実行結果のように、OverridedSub4クラスのprintMyName()メソッドが呼び出されています。
 refSuper変数はスーパークラス・HasOneMethodSuper4クラスなのに、呼び出されたのはサブクラス・OverridedSub4クラスのprintMyName()メソッドということです。

 なぜこのようになるかというと、「オーバーライドされたメソッドからオーバーライドしたメソッドへひもが付いている」からです。

 「5.3 オーバーライドで「上書き」する」で説明したように、メソッドをオーバーライドすると、オーバーライドされたメソッドからオーバーライドしたメソッドへひもが付けられ、「オーバーライドしたメソッド」が呼び出されるようになります。
 そのため、スーパークラスの参照型変数を通して呼び出しても、「オーバーライドしたメソッド」が呼び出されます
 refSuper変数はスーパークラスの参照型変数ですので、スーパークラスのprintMyName()メソッドが呼び出されようとするのですが、このメソッドはサブクラスでオーバーライドしているので、自動的にサブクラスのprintMyName()メソッドが呼び出されるわけです。

 実は、これは「5.4 オーバーライドされたメソッドを呼び出すと?」と同じ現象です。
 あの時も、スーパークラスのprintMyName()メソッドを呼び出したと思ったら、サブクラスのprintMyName()メソッドが自動的に呼び出されていました。
 オーバーライドをすることで、一見スーパークラスのメソッドを呼び出したように見えて、実はサブクラスにある「オーバーライドしたメソッド」が呼び出されるようになるわけです。

7.3 オーバーライドされたメソッドを呼び出すと?再び
このページは、Java言語を用いたオブジェクト指向プログラミングのチュートリアル解説を行う「Javaのオブジェクト指向入門」の一ページです。
詳しい説明は「Javaのオブジェクト指向入門」目次をご覧ください。