#pragma twice

KAB-studio > プログラミング > Javaのオブジェクト指向入門 > 6. 継承Q and A > 6.4 「すごい」クラスなのに「サブ」クラス?
 
前のページへつぎ

6.4 「すごい」クラスなのに「サブ」クラス?

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

「サブ」クラスじゃないやん!

 質問:「サブクラス」の「サブ」には「予備」といった語感がありますが、サブクラスはスーパークラスのフィールド・メソッドも持っているので、むしろサブクラスの方が「スーパーなクラス」じゃないですか? 語感とイメージが一致しません。
 解答:それは勘違いです。サブクラスはスーパークラスのフィールド・メソッドなんて持っていませんよ?

 恐らく皆さんは「サブクラスって実はスーパーじゃね?」と疑問に思うことでしょう。
 サブクラスはスーパークラスのフィールド・メソッドが使えてさらに自分のフィールド・メソッドまで使えるわけですから、「スーパー」と「サブ」が逆なんじゃ、と思われるかもしれません。
 でもよく考えてみましょう。本当にサブクラスはスーパークラスのフィールド・メソッドを持っていますか?

 「5.2 継承で機能を加える」で紹介したNormalSuperクラスとAddedSubクラスで考えてみましょう。

// AddedSubRunner.java

/**
 * 普通のクラス。
 * (SuperClassと全く同じクラスです)
 */
class NormalSuper
{
    // int型変数のdataフィールドです。
    int data;

    /**
     * フィールドを出力するメソッドです。
     */
    void printData()
    {
        System.out.println( data );
    }
}

/**
 * NormalSuperクラスから継承した、サブクラス。
 * フィールドとメソッドを追加しています。
 */
class AddedSub extends NormalSuper
{
    // int型変数のdataSubフィールドです。
    int dataSub;

    /**
     * フィールドを出力するメソッドです。
     */
    void printDataSub()
    {
        // このクラスで追加したフィールドを出力。
        System.out.println( dataSub );

        // ついでにスーパークラスのフィールドも出力。
        System.out.println( data );
    }
}

/**
 * 実行用クラス。このクラスを実行してください。
 */
class AddedSubRunner
{
    public static void main( String[] args )
    {
        // インスタンスを1つ作り数値を入れます。
        AddedSub ref = new AddedSub();
        // スーパークラスのフィールドに値を入れて出力します。
        ref.data = 100;
        ref.printData();
        // 出力結果:
        // 100

        // サブクラスのフィールドに値を入れて出力します。
        ref.dataSub = 200;
        ref.printDataSub();
        // 出力結果:
        // 200
        // 100
    }
}
// AddedSubRunner.java
/**
 * 普通のクラス。
 * (SuperClassと全く同じクラスです)
 */
class NormalSuper
{
	// int型変数のdataフィールドです。
	int data;
	/**
	 * フィールドを出力するメソッドです。
	 */
	void printData()
	{
		System.out.println( data );
	}
}
/**
 * NormalSuperクラスから継承した、サブクラス。
 * フィールドとメソッドを追加しています。
 */
class AddedSub extends NormalSuper
{
	// int型変数のdataSubフィールドです。
	int dataSub;
	/**
	 * フィールドを出力するメソッドです。
	 */
	void printDataSub()
	{
		// このクラスで追加したフィールドを出力。
		System.out.println( dataSub );
		// ついでにスーパークラスのフィールドも出力。
		System.out.println( data );
	}
}
/**
 * 実行用クラス。このクラスを実行してください。
 */
class AddedSubRunner
{
	public static void main( String[] args )
	{
		// インスタンスを1つ作り数値を入れます。
		AddedSub ref = new AddedSub();
		// スーパークラスのフィールドに値を入れて出力します。
		ref.data = 100;
		ref.printData();
		// 出力結果:
		// 100
		// サブクラスのフィールドに値を入れて出力します。
		ref.dataSub = 200;
		ref.printDataSub();
		// 出力結果:
		// 200
		// 100
	}
}

 NormalSuperクラスがスーパークラスです。

/**
 * 普通のクラス。
 * (SuperClassと全く同じクラスです)
 */
class NormalSuper
{
    // int型変数のdataフィールドです。
    int data;

    /**
     * フィールドを出力するメソッドです。
     */
    void printData()
    {
        System.out.println( data );
    }
}
/**
 * 普通のクラス。
 * (SuperClassと全く同じクラスです)
 */
class NormalSuper
{
	// int型変数のdataフィールドです。
	int data;
	/**
	 * フィールドを出力するメソッドです。
	 */
	void printData()
	{
		System.out.println( data );
	}
}

 そしてAddedSubクラスがサブクラスです。

/**
 * NormalSuperクラスから継承した、サブクラス。
 * フィールドとメソッドを追加しています。
 */
class AddedSub extends NormalSuper
{
    // int型変数のdataSubフィールドです。
    int dataSub;

    /**
     * フィールドを出力するメソッドです。
     */
    void printDataSub()
    {
        // このクラスで追加したフィールドを出力。
        System.out.println( dataSub );

        // ついでにスーパークラスのフィールドも出力。
        System.out.println( data );
    }
}
/**
 * NormalSuperクラスから継承した、サブクラス。
 * フィールドとメソッドを追加しています。
 */
class AddedSub extends NormalSuper
{
	// int型変数のdataSubフィールドです。
	int dataSub;
	/**
	 * フィールドを出力するメソッドです。
	 */
	void printDataSub()
	{
		// このクラスで追加したフィールドを出力。
		System.out.println( dataSub );
		// ついでにスーパークラスのフィールドも出力。
		System.out.println( data );
	}
}

 よく見てみましょう。AddedSubクラスに、NormalSuperクラスは入っていますか? 入っていません。あくまでNormalSuperクラスとAddedSubクラスは別々です。継承をしても、スーパークラスとサブクラスがくっついちゃってるわけじゃないんです。
 「でもサブクラスを通してスーパークラスのフィールド・メソッドが使えるじゃないか」と思うかもしれません。でもそれはちょっと違います。
 「サブクラスを通して」じゃないんです。
 「サブクラスのインスタンスを通して」なんです。

 「サブクラスのインスタンス」は、スーパークラスのインスタンスも持っています。そのため、サブクラスのインスタンスを通して、スーパークラスのインスタンスが持つフィールドやメソッドを使うことができます。
 そう。
 つまり「すごい」のはサブクラスのインスタンスなのです。サブクラスのインスタンスはスーパークラスのインスタンスも持っているわけですから、スーパークラスのインスタンス単体よりすごいわけです。
 でもこれは、あくまで「サブクラスのインスタンス」。「サブクラスそのもの」じゃありません。サブクラスはサブクラスであって、インスタンスとは別物です。

 また、「サブクラスのインスタンス」を「サブインスタンス」とは言いません
 「サブクラスのインスタンス」は常に「スーパークラスのインスタンス」を持っています。
 「スーパークラスのインスタンス」を持たない「サブクラスのインスタンス」はありません。
 なので、「サブクラスのインスタンス」は常に「スーパークラスのインスタンス」より「すごい」わけです。

 クラスはインスタンスの設計図です。
 スーパークラスとサブクラスに設計図が書かれていて、それらを元にインスタンスを作ります。
 できたインスタンスは、各設計図によって作られた「1つの実体」というわけです。

6.4 「すごい」クラスなのに「サブ」クラス?
このページは、Java言語を用いたオブジェクト指向プログラミングのチュートリアル解説を行う「Javaのオブジェクト指向入門」の一ページです。
詳しい説明は「Javaのオブジェクト指向入門」目次をご覧ください。