質問: JAVAを勉強している者です。説明が下手ですいませんが、オブジェクト指向の「抽象」及び「抽象クラス」って一体何なんでしょうか? ネットや参考書みても「あいまいな及びあいまいなクラス」と書いてあるんですが、何なのかよくわかりません。 まだ勉強不足だと思いますが、「抽象」というのは、「プログラムの処理内容がまだ確定(未完成?)していない、詳細未定(未完成?)メソッド」みたいなことが書かれてありました。 さらに、「抽象クラス」というのは「フィールドと詳細未定(未完成?)メソッドが存在するクラス」みたいなことが書かれてあり、その「詳細未定(未完成?)メソッドがたくさん存在するほど抽象度(あいまい度)が高いクラス」という風に書かれていました。(説明が下手ですいません。) そもそも「プログラムの処理内容がまだ確定(未完成?)していない、詳細未定(未完成?)」というのは、しっかりと設計していないことであり、きちんと完璧に設計すればいいと思うのですが、なぜそんなことがあり得るんですか? それに「プログラムの処理内容がまだ確定(未完成?)していない、詳細未定(未完成?)」は多人数で開発していると起こりやすいと思いますが、一人での開発ではそんなことは起きないのでは?と思っております。 わかりやすいような例や例えで教えてくれませんか? できれば身近な例を挙げて教えてくれませんか? よろしくお願いします。
回答: 抽象クラスは、それそのものだけでなく多態性(ポリモルフィズム)を使用した時に真価が発揮されるように思えます 以下が具体的にどう役に立つのかのコード例です 抽象クラスの概念がある事で、実装クラスの中身が実装クラスごとに変化しても一括してそれらを扱えるようにできる事が分かると思います 身近な例を用いて説明しました ファイル名:Jyuyou.java ``` abstract class 死 {// 抽象クラス int i = 0; abstract void 否認();// 自分の死そのものを疑う段階 abstract void 怒り();// 自分が死ぬことへの怒りを感じている段階 abstract void 取り引き();// 死を免れようとあがき回る段階 abstract void 抑うつ();// 気分が落ち込み何もできない段階 abstract void 受容();// 死をついに受け入れた段階 void 死の受容過程() {// 上記過程の連続再生 System.out.println("死の受容例" + (i + 1) + "人目"); slp(); System.out.println("\n---" + (i + 1) + "人目:" + "死の受容の過程1~否認~---"); slp(); 否認(); slp(); System.out.println("\n---" + (i + 1) + "人目:" + "死の受容の過程2~怒り~---"); slp(); 怒り(); slp(); System.out.println("\n---" + (i + 1) + "人目:" + "死の受容の過程3~取り引き~---"); slp(); 取り引き(); slp(); System.out.println("\n---" + (i + 1) + "人目:" + "死の受容の過程4~抑うつ~---"); slp(); 抑うつ(); slp(); System.out.println("\n---" + (i + 1) + "人目:" + "死の受容の過程5~受容~---"); slp(); 受容(); slp(); System.out.println("\n\n\n\n"); slp(); } void set(int o) {// 何人目か i = o; } void slp() {// 表示間隔 try { Thread.sleep(600); } catch (Exception e) { } } } class 死を待つ人1 extends 死 {// 抽象クラスを実装したクラス1 void 否認() { System.out.println("私は癌ではありません 検査のやり直しを要求します"); } void 怒り() { System.out.println("何で俺が死ななきゃならないんだ! 死にたくないって言ってるだろ!"); } void 取り引き() { System.out.println("すみません 癌の特効薬があると言うのはこちらですか"); } void 抑うつ() { System.out.println("死にたくありません 僕は死にたくないんです"); } void 受容() { System.out.println("最近、死ぬのも悪くないって思えるようになったんです"); } } class 死を待つ人2 extends 死 {// 抽象クラスを実装したクラス2 void 否認() { System.out.println("あの医者俺が死ぬなんて嘘なんでついたんだろ"); } void 怒り() { System.out.println("やめろ・・・死ぬとかそんなの本人に言っていいと思ってるのか!"); } void 取り引き() { System.out.println("分かりました 分かりました食事療法で少しでも生きられるんですね"); } void 抑うつ() { System.out.println("嫌だ・・死にたくない・・・・耐えられない・・・・"); slpl(); for (int i = 0; i < 400; i++) { System.out.print("死にたくない "); } System.out.println(); } void 受容() { System.out.println("昨日お迎えが来る夢を見たんです"); } void slpl() { try { Thread.sleep(2000); } catch (Exception e) { } } } class 死を待つ人3 extends 死 {// 抽象クラスを実装したクラス3 void 否認() { System.out.println("昨日死の宣告を受ける夢を見た リアルだったが夢は夢だ そうだあれは夢だ"); } void 怒り() { System.out.println("俺が死んだら残された皆はどうなるんだ! そんなの認められるはずがないだろうが!"); } void 取り引き() { System.out.println("この万病に効くエキスさえあれば・・・"); } void 抑うつ() { for (int i = 0; i < 25; i++) { System.out.print("嫌だ・・・死にたくない・・・ "); slpl(); System.out.print("あの頃・・・食事に気を付けてさえいれば・・・ "); slpl(); System.out.print("これは夢だ・・・夢だ・・・ "); slpl(); } System.out.println(); } void 受容() { System.out.println("僕が死ぬことは最初から定められていた運命だったんです だからこれは仕方のない事なんです"); } void slpl() { try { Thread.sleep(50); } catch (Exception e) { } } } class Jyuyou { public static void main(String[] args) { 死 a[] = new 死[3];// 配列変数aに全ての実装クラスのインスタンスを一括して入れられる(多態性) a[0] = new 死を待つ人1(); a[1] = new 死を待つ人2(); a[2] = new 死を待つ人3(); for (int i = 0; i < 3; i++) {// このfor文の中で行われる操作は //a配列の中に入るクラス死の実装クラスをどれだけ増やしても同じで済む a[i].set(i); a[i].死の受容過程(); } } } ```