質問)
abstractを付与したクラスAがあると仮定します。
クラスAから、クラスBを継承させます。
クライアント側で、オブジェクトを生成する際に
クラスA 変数名 = new クラスB();
「変数として宣言しているクラスA」と「オブジェクト生成している(メモリ確保)クラスB」
と記述可能なメリットと理由がよくわかりません。
クラスA(absract)がオブジェクト生成できないため、
あえてクラスBを生成するってことなのでしょうか?
上の例だと、クラスBのメソッドは呼び出すことはできない筈なので。
サブクラスのアドレスを基底クラスの変数に格納しても問題ないってこと?
これは、基底クラスの領域しかアドレスを読み込めないってことなのでしょうか?
質問者様の疑問は、オブジェクト指向プログラミングをする上でよくある疑問だと思います。
すべてに言及すると本一冊以上のボリュームになってしまいますので
ここではヒントになりそうなコメントをさせていただきます。
なお、「オブジェクト脳のつくり方」という本が、このテーマをわかりやすく説明していると思います。
また、以下の説明ではabstractクラスのほかにinterfaceも説明に使いますが意味は同じです。
(それ自体で実体化できない・継承した実装クラスを使うなど)
まず「サブクラスのアドレスを基底クラスの変数に格納しても問題ないか?」ですが、
問題ないと考えてください。
「基底クラスの領域しかアドレスを読み込めない」ことになりますが、それで構いません。
なぜなら、基底クラスで定義しているメソッド/APIしか使わないために、あえてそうしているからです。
クライアントのコードでは
クラスA 変数名 = new クラスB(); ・・・(1)
とした後、変数名に対して、いろいろなメソッドを呼び出す使い方をするでしょうが、
これ以降ではクラスBのことは意識しないようにしています。
あくまでクラスAのメソッド/APIのみを使ってコーディングをするようにします。
「なぜ機能が多いクラスBでなく機能が制限されたクラスAを使うのか?」というのが次に感じる疑問だと思います。
それは、
・クラスBの機能をすべてクライアントに見せることはしたくない → 「隠蔽」
・クラスAを継承した別の実装クラスCを使いたくなったときに、上記(1)以降のクライアントコードをいじる必要がない → 「ポリモーフィズム」
というメリットがあるためです。
オブジェクト指向の入門本などを読むと、よく自動車や動物などの例を出して上記隠蔽やポリモーフィズムを説明していますが
他に具体例を知りたい場合は、Java言語自体のListインターフェースやその実装クラスであるArrayList,Vector,LinkedListクラスなどを勉強すると頭に入りやすいかもしれません。
クラスA 変数名あ = new クラスB();
クラスA 変数名い = new クラスC();
変数名あと変数名いは、同様のクラスの型として扱えるので便利です。
クラスAというのは「型名」で、生成するのはnew で書いたクラスです。
>クラスA(absract)がオブジェクト生成できないため、
>あえてクラスBを生成するってことなのでしょうか?
間違ってます。
>サブクラスのアドレスを基底クラスの変数に格納しても問題ないってこと?
はい
>これは、基底クラスの領域しかアドレスを読み込めないってことなのでしょうか?
間違っています。
クラスA 変数名;・・・①
これは、クラスAがメモリ上に割り当てられて状態?(実領域は割り当てられていない)
C言語だと、ポインタ変数を定義した状態だと思います。 int *p;
変数名 = new クラスB();
これは、クラスBのメモリを確保し(オブジェクト生成)、そのアドレスを変数名に確保している?