Java継承と抽象クラスの実践的学習

第一部分:理論知識の学習

第五章:継承と多様性

第五章の学習内容は主に七つのモジュールに分かれています:

  1. クラス、スーパークラス、サブクラス a. クラス継承の形式:class 新しいクラス名 extends 既存クラス名

b. 既存のクラスは:スーパークラス(superclass)、基底クラス(base class)または親クラス(parent class)と呼ばれます 新しいクラスは:サブクラス(subclass)、派生クラス(derived class)または子クラス(child class)と呼ばれます

c. superはコンパイラにスーパークラスのメソッドを呼び出すことを指示する特別なキーワードです。これはオブジェクトの参照ではなく、別のオブジェクト変数にsuperを割り当てることはできません

d. あるスーパークラスから拡張されたクラスの集合を継承階層と呼びます。継承階層では、あるクラスからその祖先へのパスがそのクラスの継承チェーンと呼ばれます

注:Javaは多重継承をサポートしていません。

e. 多様性(ポリモーフィズム):プログラム内で同じ記号が異なる状況下で異なる解釈を持つ現象を指します

f. 継承を許可しないクラスをfinalクラスと呼びます。クラスの定義ではfinal修飾子を使用して説明します

g. 抽象クラス:抽象メソッドは占め役として機能し、その具体的な実装はサブクラスにあります。 抽象クラスはインスタンス化できず、オブジェクトを作成することはできません。サブクラスのみを生成できます。

  1. Object:すべてのクラスのスーパークラス a. ObjectクラスはJavaにおけるすべてのクラスの祖先です——すべてのクラスはこれから拡張されます。スーパークラスが指定されていない場合、Javaは自動的にObjectを定義するクラスのスーパークラスとして使用します。

b. Object型の変数を使用して任意の型のオブジェクトを指すことができます。しかし、それらを特定の操作で使用するには型変換が必要です。

c. Objectクラスのequalsメソッドは、あるオブジェクトが別のオブジェクトと等しいかどうかをテストするために使用されます。Objectクラスでの実装は、2つのオブジェクトが同じ参照を持つかどうかを判断します。2つのオブジェクトが同じ参照を持つ場合、それらは必ず等しいです。

d. ObjectクラスのhashCodeメソッドは、あるオブジェクトのハッシュコードを導き出します。ハッシュコードは任意の整数で、オブジェクトの保存アドレスを表します。

等しいオブジェクトのハッシュコードは等しいです。

  1. ジェネリック配列リスト a. Javaでは、ArrayListクラスを使用して、プログラムの実行時に配列のサイズを動的に決定できます。

b. ArrayListは型パラメータを使用するジェネリッククラスです。配列リストが要素として保存するオブジェクトの型を指定するには、要素のオブジェクトクラス名を角括弧で囲んで後に追加する必要があります。

ArrayList<従業員> スタッフ = new ArrayList<従業員>();

  1. オブジェクトラッパーとオートボクシング a. すべての基本データ型には対応する事前定義されたクラスがあり、それらはオブジェクトラッパーと呼ばれます。

b. オブジェクトラッパークラスは不変であり、一度ラッパーが構築されると、ラップされている値の変更は許可されません。また、オブジェクトラッパークラスはfinalでもあるため、サブクラスを定義することはできません。

c. JavaSE5.0では、基本データ型をラッパークラスのオブジェクトに自動的に変換できます。この変換をオートボクシングと呼びます。

  1. 可変引数メソッド a. Java SE 5.0以前のバージョンでは、各Javaメソッドは固定数のパラメータを持っていました。しかし、現在のバージョンでは、可変数の引数で呼び出せるメソッド(「可変引数」メソッド)が提供されています。

b. ユーザーは自分で可変引数メソッドを定義でき、パラメータを任意の型、甚至是基本型として指定できます。

  1. 列挙クラス a. 列挙クラスの宣言 public enum 成績{A,B,C,D,E};

これはキーワードenum、新しい列挙型の名前成績、および成績用に定義された一連の値を含みます。ここでの値は整数型でも文字型でもありません。

b. 列挙クラスはクラスであり、その暗黙のスーパークラスはjava.lang.Enumです。

c. 列挙値は整数や他の型ではなく、宣言された列挙クラス自身のインスタンスです。

  1. 継承設計のヒント a. 共通の操作とフィールドをスーパークラスに配置します。

b. protectedフィールドを使用しないでください。

c. 継承を使用して「is-a」関係を実装します。

d. すべての継承されたメソッドに意味がある場合を除き、継承を使用しないでください。

e. メソッドをオーバーライドする際、期待される動作を変更しないでください。

f. 型情報ではなく、多様性を使用します。

g. リフレクションの過度な使用。

第二部分:実践的実験

実験6:継承の定義と使用

  1. 実験の目的と要件 (1) 継承の定義を理解する; (2) サブクラスの定義要件を習得する (3) 多様性の概念と使用法を習得する; (4) 抽象クラスの定義と用途を習得する; (5) クラスの4つのメンバアクセス修飾子の用途を習得する; (6) 抽象クラスの定義方法と用途を習得する; (7) Objectクラスの用途と一般的なAPIを習得する; (8) ArrayListクラスの定義方法と使用法を習得する; (9) 列挙クラスの定義方法と用途を習得する。

  2. 実験の内容と手順

実験1: 第5章のサンプルプログラムをインポートし、テストしてコードにコメントを追加する。

テストプログラム1:

1)Eclipse IDEでプログラム5-1(教科書152-153ページ)を編集、デバッグ、実行します; 2)サブクラスの定義と使用法を習得します; 3)プログラムの実行結果に基づき、OOスタイルのプログラム構造の特徴を理解し、要約します。従業員とマネージャークラスの関係とサブクラスの用途を理解し、コードにコメントを追加します。

プログラム5-1は以下の通りです:

 1 package 継承;

 2 /**
 3  * このプログラムは継承を示します。
 4  * @version 1.21 2004-02-21
 5  * @author Cay Horstmann
 6  */
 7 public class マネージャーテスト
 8 {
 9    public static void main(String[] args)
10    {
11       // マネージャーオブジェクトの構築
12       マネージャー 上司 = new マネージャー("Carl Cracker", 80000, 1987, 12, 15);
13       上司.setBonus(5000);
14 
15       従業員[] スタッフ = new 従業員[3];
16 
17       // マネージャーと従業員オブジェクトでスタッフ配列を埋める
18 
19       スタッフ[0] = 上司;
20       スタッフ[1] = new 従業員("Harry Hacker", 50000, 1989, 10, 1);
21       スタッフ[2] = new 従業員("Tommy Tester", 40000, 1990, 3, 15);
22 
23       // すべての従業員オブジェクトの情報を出力
24       for (従業員 e : スタッフ)
25          System.out.println("名前=" + e.getName() + ",給料=" + e.getSalary());
26    }
27 }

従業員クラス:

 1 package 継承;

 2 import java.time.*;
 3 
 4 public class 従業員
 5 {
 6    private String 名前;//3つの非公開オブジェクトを構築
 7    private double 給料;
 8    private LocalDate 雇用日;
 9 
10    public 従業員(String 名前, double 給料, int 年, int 月, int 日)
11    {
12       this.名前 = 名前;
13       this.給料 = 給料;
14       雇用日 = LocalDate.of(年, 月, 日);
15    }
16 
17    public String getName()
18    {
19       return 名前;
20    }
21 
22    public double getSalary()
23    {
24       return 給料;
25    }
26 
27    public LocalDate getHireDay()
28    {
29       return 雇用日;
30    }
31 
32    public void raiseSalary(double パーセント)
33    {
34       double 昇給 = 給料 * パーセント / 100;
35       給料 += 昇給;
36    }
37 }

マネージャークラス:

 1 package 継承;
 2 //キーワードextendsは継承を示します。これは既存のクラスから派生した新しいクラスを構築していることを示します。既存のクラスはスーパークラス/基底クラス/または親クラスと呼ばれます;新しいクラスはサブクラス/派生クラス/または子クラスと呼ばれます。
 3 public class マネージャー extends 従業員
 4 {
 5    private double ボーナス;
 6 
 7    /**
 8     * @param name 従業員の名前
 9     * @param salary 給料
10     * @param year 雇用年
11     * @param month 雇用月
12     * @param day 雇用日
13     */
14    public マネージャー(String 名前, double 給料, int 年, int 月, int 日)
15    {//以下の文は、n、s、年、月、日パラメータを持つスーパークラスのコンストラクタを呼び出す意味です。
16       super(名前, 給料, 年, 月, 日);
17       ボーナス = 0;
18    }
19 
20    public double getSalary()
21    {  //サブクラスがスーパークラスのメソッドにアクセスするには、特定のキーワードsuperを使用する必要があります。
22        //コンストラクタを呼び出すsuper文は、サブクラスのコンストラクタの最初の文でなければなりません。
23       double 基本給 = super.getSalary();
24       return 基本給 + ボーナス;
25    }
26 
27    public void setBonus(double b)
28    {
29       ボーナス = b;
30    }
31 }

プログラムの実行結果は以下の通りです:

**プログラムの要約:**サブクラスの定義は個人的には、extendsキーワードを使用して継承操作を行うだけでよいと思います。以下のコードのように:

class 基底クラス{    //親クラス
    //......
}
class 新しいクラス extends 基底クラス{    //子クラス
    //......
}

クラスを構築する際、宣言時に親クラスを使用し、具体的なコンストラクタでは子クラスを使用できます。生成されたオブジェクトは親クラス型のオブジェクトであり、つまりこのオブジェクトには現在親クラスの属性とメソッドしかありませんが、子クラスがオーバーライドする場合は、子クラスのオーバーライドされたメソッドを使用する必要があります。

OOスタイルのプログラム構造の特徴については、大体四つあると思います。すなわち:抽象化、カプセル化、継承、多様性です。

a) カプセル化:一部または全部の属性と一部の機能(関数)を外部から隠蔽し、外部(クラスの波括弧の外)から見えず、知ることができないようにします。

カプセル化の二つの側面:一是関連データと操作コードをオブジェクトにカプセル化し、一つの基本単位とし、各オブジェクトは相互に独立し、互いに干渉しません。

二はオブジェクトの一部の属性と操作をプライベート化し、データと操作情報の隠蔽を実現し、データセキュリティに役立ち、無関係者による変更を防止します。

b) オブジェクト指向の継承:ソフトウェアの再利用のためであり、簡単に言えばコードの再利用です。重複使用されるコードを簡略化する手段です。どのように簡略化するかというと、あるクラスにすでに対応する属性と操作コードがあり、別のクラスでも同じコードを書く必要がある場合、継承方法を使用し、前のクラスを親クラスとし、後のクラスを子クラスとし、子クラスが親クラスを継承します。一つのキーワードextendsでコードの再利用が完了します。

c) 多様性:継承がなければ多様性はありません。継承は多様性の前提です。同じ親クラスから継承されていても、対応する操作は各々異なり、これを多様性と呼びます。継承によって生じた異なる派生クラスは、そのオブジェクトが同じメッセージに対して異なる応答をします。

テストプログラム2:

  1. 教科書のPersonTestプログラム(教科書163-165ページ)を編集、コンパイル、デバッグ、実行します;
  2. スーパークラスの定義とその使用要件を習得します;
  3. スーパークラスを使用してサブクラスを拡張する要件を習得します;
  4. プログラムの関連コードに新しい知識のコメントを追加します。

プログラム5-4は以下の通りです:

 1 package 抽象クラス;

 2 /**
 3  * このプログラムは抽象クラスを示します。
 4  * @version 1.01 2004-02-21
 5  * @author Cay Horstmann
 6  */
 7 public class テスト
 8 {
 9    public static void main(String[] args)
10    {
11 //       抽象クラスの宣言ですが、抽象クラスをインスタンス化することはできません。インスタンス化されるのはPersonクラスのサブクラスです
12 //      親クラスの参照は子クラスのオブジェクトを参照できます。なぜなら親クラスの参照のメソッドは子クラスのオブジェクトのメソッドを超えないからですが、その逆はできません
13       人[] 人々 = new 人[2];
14 
15       // 学生と従業員で人物配列を埋める
16       人々[0] = new 従業員("Harry Hacker", 50000, 1989, 10, 1);
17       人々[1] = new 学生("Maria Morris", "computer science");
18 
19       // すべての人オブジェクトの名前と説明を出力
20       for (人 p : 人々)
21          System.out.println(p.getName() + ", " + p.getDescription());
22    }
23 }

学生クラス

 1 package 抽象クラス;

 2 public class 学生 extends 人
 3 {
 4    private String 専門分野;
 5 
 6    /**
 7     * @param name 学生の名前
 8     * @param major 学生の専門分野
 9     */
10    public 学生(String 名前, String 専門分野)
11    {
12       // 総綱コンストラクタを介して
13       super(名前);
14       this.専門分野 = 専門分野;
15    }
16 
17    public String getDescription()
18    {
19       return "a student majoring in " + 専門分野;
20    }
21 }

人クラス

 1 package 抽象クラス;

 2 public abstract class 人
 3 {
 4      //一つ以上の抽象メソッドを含むクラスは抽象クラスと呼ばれ、abstractキーワードで修飾されます
 5     //一般的なスコープとメソッドもここに置かれており、抽象クラスはインスタンス化できませんが、宣言はできます
 6    public abstract String getDescription();
 7    private String 名前;
 8 
 9    public 人(String 名前)
10    {
11       this.名前 = 名前;
12    }
13 
14    public String getName()
15    {
16       return 名前;
17    }
18 }

従業員クラス

 1 package 抽象クラス;

 2 import java.time.*;
 3 
 4 public class 従業員 extends 人
 5 {
 6    private double 給料;
 7    private LocalDate 雇用日;
 8 
 9    public 従業員(String 名前, double 給料, int 年, int 月, int 日)
10    {
11       super(名前);
12       this.給料 = 給料;
13       雇用日 = LocalDate.of(年, 月, 日);
14    }
15 
16    public double getSalary()
17    {
18       return 給料;
19    }
20 
21    public LocalDate getHireDay()
22    {
23       return 雇用日;
24    }
25 
26  //親クラスのメソッドをオーバーライドし、フォーマットされた文字列を返す
27    public String getDescription()
28    {
29       return String.format("an employee with a salary of $%.2f", 給料);
30    }
31 
32    public void raiseSalary(double パーセント)
33    {
34       double 昇給 = 給料 * パーセント / 100;
35       給料 += 昇給;
36    }
37 }

プログラムの実行結果は以下の通りです:

テストプログラム3:

  1. 教科書プログラム5-8、5-9、5-10を編集、コンパイル、デバッグ、実行し、プログラムの実行結果に基づいてプログラムを理解します(教科書174-177ページ);
  2. Objectクラスの定義と使用法を習得します;
  3. プログラムの関連コードに新しい知識のコメントを追加します。

プログラム5-8は以下の通りです:

 1 package 等価性;

 2 /**
 3  * このプログラムはequalsメソッドを示します。
 4  * @version 1.12 2012-01-26
 5  * @author Cay Horstmann
 6  */
 7 public class 等価性テスト
 8 {
 9    public static void main(String[] args)
10    {
11       従業員 alice1 = new 従業員("Alice Adams", 75000, 1987, 12, 15);
12       従業員 alice2 = alice1;
13       従業員 alice3 = new 従業員("Alice Adams", 75000, 1987, 12, 15);
14       従業員 bob = new 従業員("Bob Brandson", 50000, 1989, 10, 1);
15 
16       System.out.println("alice1 == alice2: " + (alice1 == alice2));
17 
18       System.out.println("alice1 == alice3: " + (alice1 == alice3));
19 
20       System.out.println("alice1.equals(alice3): " + alice1.equals(alice3));
21 
22       System.out.println("alice1.equals(bob): " + alice1.equals(bob));
23 
24       System.out.println("bob.toString(): " + bob);
25 
26       マネージャー carl = new マネージャー("Carl Cracker", 80000, 1987, 12, 15);
27       マネージャー boss = new マネージャー("Carl Cracker", 80000, 1987, 12, 15);
28       boss.setBonus(5000);
29       System.out.println("boss.toString(): " + boss);
30       System.out.println("carl.equals(boss): " + carl.equals(boss));
31       System.out.println("alice1.hashCode(): " + alice1.hashCode());
32       System.out.println("alice3.hashCode(): " + alice3.hashCode());
33       System.out.println("bob.hashCode(): " + bob.hashCode());
34       System.out.println("carl.hashCode(): " + carl.hashCode());
35    }
36 }

マネージャークラス

 1 package 等価性;

 2 public class マネージャー extends 従業員
 3 {
 4    private double ボーナス;
 5 
 6    public マネージャー(String 名前, double 給料, int 年, int 月, int 日)
 7    {
 8       super(名前, 給料, 年, 月, 日);
 9       ボーナス = 0;
10    }
11 
12    public double getSalary()
13    {
14       double 基本給 = super.getSalary();
15       return 基本給 + ボーナス;
16    }
17 
18    public void setBonus(double ボーナス)
19    {
20       this.ボーナス = ボーナス;
21    }
22 
23    public boolean equals(Object 他のオブジェクト)
24    {
25       if (!super.equals(他のオブジェクト)) return false;
26       マネージャー 他 = (マネージャー) 他のオブジェクト;
27       // これと他が同じクラスであるかをチェック
28       return ボーナス == 他.ボーナス;
29    }
30 
31    public int hashCode()
32    {
33       return java.util.Objects.hash(super.hashCode(), ボーナス);
34    }
35 
36    public String toString()
37    {
38       return super.toString() + "[ボーナス=" + ボーナス + "]";
39    }
40 }

従業員クラス

 1 package 等価性;

 2 import java.time.*;
 3 import java.util.Objects;
 4 
 5 public class 従業員
 6 {
 7    private String 名前;
 8    private double 給料;
 9    private LocalDate 雇用日;
10 
11    public 従業員(String 名前, double 給料, int 年, int 月, int 日)
12    {
13       this.名前 = 名前;
14       this.給料 = 給料;
15       雇用日 = LocalDate.of(年, 月, 日);
16    }
17 
18    public String getName()
19    {
20       return 名前;
21    }
22 
23    public double getSalary()
24    {
25       return 給料;
26    }
27 
28    public LocalDate getHireDay()
29    {
30       return 雇用日;
31    }
32 
33    public void raiseSalary(double パーセント)
34    {
35       double 昇給 = 給料 * パーセント / 100;
36       給料 += 昇給;
37    }
38 
39    public boolean equals(Object 他のオブジェクト)
40    {
41       // オブジェクトが同じかどうかを迅速にチェック
42 //       ここではオブジェクトパラメータを取得し、最初のif文は2つの参照が同じかどうかを判断します。同じであれば、これら2つのオブジェクトは確かに等しいです
43       if (this == 他のオブジェクト) return true;
44 
45       // 明示的なパラメータがnullの場合、falseを返す必要があります
46       if (他のオブジェクト == null) return false;
47 
48 //      getClass()メソッドはオブジェクトのクラスを取得します。ここでは2つのオブジェクトのクラスが異なる場合、等しくないということです
49       if (getClass() != 他のオブジェクト.getClass()) return false;
50 
51       // ここで、もう一方のオブジェクトが非nullの従業員であることがわかっています
52 //      上記の判断が完了した後、得られたパラメータオブジェクトをそのオブジェクトにキャストします。親クラス参照子クラスオブジェクトの出現を考慮し、次にオブジェクトの属性が同じかどうかを判断します
53       従業員 他 = (従業員) 他のオブジェクト;
54 
55       // フィールドが同じ値を持つかどうかをテスト
56       return Objects.equals(名前, 他.名前) && 給料 == 他.給料 && Objects.equals(雇用日, 他.雇用日);
57    }
58 
59    public int hashCode()
60 //   ハッシュ散列
61    {
62       return Objects.hash(名前, 給料, 雇用日); 
63    }
64 // toString()メソッド、自動生成可能
65    public String toString()
66    {
67       return getClass().getName() + "[名前=" + 名前 + ",給料=" + 給料 + ",雇用日=" + 雇用日
68             + "]";
69    }
70 }

プログラムの実行結果:

テストプログラム4:

  1. Eclipse IDEでプログラム5-11をデバッグ、実行し(教科書182ページ)、プログラムの実行結果に基づいてプログラムを理解します;
  2. ArrayListクラスの定義と使用法を習得します;
  3. プログラムの関連コードに新しい知識のコメントを追加します。

プログラム5-11は以下の通りです:

 1 package 配列リスト;

 2 import java.util.*;

 3 /**
 4  * このプログラムはArrayListクラスを示します。
 5  * @version 1.11 2012-01-26
 6  * @author Cay Horstmann
 7  */
 8 public class 配列リストテスト
 9 {
10    public static void main(String[] args)
11    {
12       // 3人の従業員オブジェクトでスタッフ配列リストを埋める
13       ArrayList<従業員> スタッフ = new ArrayList<>();
14 
15       スタッフ.add(new 従業員("Carl Cracker", 75000, 1987, 12, 15));
16       スタッフ.add(new 従業員("Harry Hacker", 50000, 1989, 10, 1));
17       スタッフ.add(new 従業員("Tony Tester", 40000, 1990, 3, 15));
18 
19       // すべての人の給料を5%上げる
20       for (従業員 e : スタッフ)
21          e.raiseSalary(5);
22 
23       // すべての従業員オブジェクトの情報を出力
24       for (従業員 e : スタッフ)
25          System.out.println("名前=" + e.getName() + ",給料=" + e.getSalary() + ",雇用日="
26                + e.getHireDay());
27    }
28 }

従業員クラス

 1 package 配列リスト;

 2 import java.time.*;
 3 
 4 public class 従業員
 5 {
 6    private String 名前;
 7    private double 給料;
 8    private LocalDate 雇用日;
 9 
10    public 従業員(String 名前, double 給料, int 年, int 月, int 日)
11    {
12       this.名前 = 名前;
13       this.給料 = 給料;
14       雇用日 = LocalDate.of(年, 月, 日);
15    }
16 
17    public String getName()
18    {
19       return 名前;
20    }
21 
22    public double getSalary()
23    {
24       return 給料;
25    }
26 
27    public LocalDate getHireDay()
28    {
29       return 雇用日;
30    }
31 
32    public void raiseSalary(double パーセント)
33    {
34       double 昇給 = 給料 * パーセント / 100;
35       給料 += 昇給;
36    }
37 }

プログラムの実行結果:

テストプログラム5:

  1. プログラム5-12を編集、コンパイル、デバッグ、実行し(教科書189ページ)、実行結果に基づいてプログラムを理解します;
  2. 列挙クラスの定義と使用法を習得します;
  3. プログラムの関連コードに新しい知識のコメントを追加します。

プログラム5-12は以下の通りです:

 1 package 列挙型;

 2 import java.util.*;

 3 /**
 4  * このプログラムは列挙型を示します。
 5  * @version 1.0 2004-05-24
 6  * @author Cay Horstmann
 7  */
 8 public class 列挙型テスト
 9 {  
10    public static void main(String[] args)
11    {  
12       Scanner in = new Scanner(System.in);
13       System.out.print("サイズを入力してください: (SMALL, MEDIUM, LARGE, EXTRA_LARGE) ");
14       String input = in.next().toUpperCase();
15       サイズ size = Enum.valueOf(サイズ.class, input);
16       System.out.println("size=" + size);
17       System.out.println("略称=" + size.getAbbreviation());
18       if (size == サイズ.EXTRA_LARGE)
19          System.out.println("よくできました--あなたは_に注意を払いました。");      
20    }
21 }
22 
23 enum サイズ
24 {
25    SMALL("S"), MEDIUM("M"), LARGE("L"), EXTRA_LARGE("XL");
26 
27    private サイズ(String 略称) { this.略称 = 略称; }
28    public String getAbbreviation() { return 略称; }
29 
30    private String 略称;
31 }

プログラムの実行結果:

実験2:プログラミング練習1

  1. 抽象クラスShapeを定義します:

属性:変更不可能な定数double PI、値は3.14; メソッド:public double getPerimeter();public double getArea())。

  1. RectangleとCircleをShapeクラスから継承させます。

  2. double sumAllAreaメソッドを記述して、形状配列の面積の合計を出力し、double sumAllPerimeterメソッドを記述して形状配列の周長の合計を出力します。

mainメソッドで

  1. 整数値nを入力し、n個の異なる形状を構築します。rectが入力された場合は、長さと幅をさらに入力します。cirが入力された場合は、半径をさらに入力します。
  2. その後、すべての形状の周長の合計、面積の合計を出力します。そして、すべての形状情報をサンプルの形式で出力します。
  3. 最後に、各形状の型と親の型を出力します。shape.getClass()(型を取得)、shape.getClass().getSuperclass()(親の型を取得)を使用します。

考え:sumAllAreaとsumAllPerimeterメソッドはどのクラスに配置するのがより適切ですか?

入力サンプル:

3
rect
1 1
rect
2 2
cir
1

出力サンプル:

18.28
8.14
[Rectangle [width=1, length=1], Rectangle [width=2, length=2], Circle [radius=1]]
class Rectangle,class Shape
class Rectangle,class Shape
class Circle,class Shape

実験コードは以下の通りです:

 1 package 形状;

 2 import java.math.*;
 3 import java.util.*;
 4 import 形状.形状;
 5 import 形状.長方形;
 6 import 形状.円形;
 7 
 8 public class 形状計算 
 9 {
10 
11     public static void main(String[] args) 
12     {
13         Scanner in = new Scanner(System.in);
14         String rect = "rect";
15         String cir = "cir";
16         System.out.print("形状の数を入力してください:");
17         int n = in.nextInt();
18         形状[] スコア = new 形状[n];
19         for(int i=0;i<n;i++)
20         {
21             System.out.println("形状タイプを入力してください (rect or cir):");
22             String input = in.next();
23             if(input.equals(rect))
24             {
25                 double 長さ = in.nextDouble();
26                 double 幅 = in.nextDouble();
27                 System.out.println("長方形["+"長さ:"+長さ+"  幅:"+幅+"]");
28                 スコア[i] = new 長方形(幅,長さ);
29             }
30             if(input.equals(cir)) 
31             {
32                 double 半径 = in.nextDouble();
33                 System.out.println("円形["+"半径:"+半径+"]");
34                 スコア[i] = new 円形(半径);
35             }
36         }
37         形状計算 c = new 形状計算();
38         System.out.println(c.sumAllPerimeter(スコア));
39         System.out.println(c.sumAllArea(スコア));
40         for(形状 s:スコア) 
41         {
42 
43             System.out.println(s.getClass()+",  "+s.getClass().getSuperclass());
44         }
45     }
46 
47     public double sumAllArea(形状 スコア[])
48     {
49          double 合計 = 0;
50          for(int i = 0;i<スコア.length;i++)
51              合計+= スコア[i].getArea();
52          return 合計;
53     }
54     
55     public double sumAllPerimeter(形状 スコア[])
56     {
57          double 合計 = 0;
58          for(int i = 0;i<スコア.length;i++)
59              合計+= スコア[i].getPerimeter();
60          return 合計;
61     }
62     
63 }
1 package 形状;

2 public abstract class 形状
3 {
4     double PI = 3.14;
5     public abstract double  getPerimeter();
6     public abstract double  getArea();
7 }
 1 package 形状;

 2 public class 長方形 extends 形状
 3 {
 4     private double 幅;
 5     private double 長さ;
 6     public 長方形(double w,double l)
 7     {
 8         this.幅 = w;
 9         this.長さ = l;
10     }
11     public double getPerimeter()
12     {
13         double 周囲 = (幅+長さ)*2;
14         return 周囲;
15     }
16     public double getArea()
17     {
18         double 面積 = 幅*長さ;
19         return 面積;
20     }
21     public String toString()
22     {
23         return getClass().getName() + "[ 幅=" +  幅 + "]"+ "[長さ=" + 長さ + "]";
24     }
25 }
 1 package 形状;

 2 public class 円形 extends 形状
 3 {
 4 
 5     private double 半径;
 6     public 円形(double r)
 7     {
 8         半径 = r;
 9     }
10     public double getPerimeter()
11     {
12         double 周囲 = 2*PI*半径;
13         return 周囲;
14     }
15     public double getArea()
16     {
17         double 面積 = PI*半径*半径;
18         return 面積;
19     }
20     public String toString()
21     {
22         return  getClass().getName() + "[半径=" + 半径 + "]";
23     }
24 }

プログラムの実行結果は以下の通りです:

実験3:プログラミング練習2

プログラムを作成し、身分証明書番号.txtの情報をメモリに読み込み、身分証明書番号または名前を入力して、検索対象の名前、身分証明書番号、年齢、性別、出身地を表示します。

実験コードは以下の通りです:

  1 package 身分証明書;

  2 import java.io.BufferedReader;
  3 import java.io.File;
  4 import java.io.FileInputStream;
  5 import java.io.FileNotFoundException;
  6 import java.io.IOException;
  7 import java.io.InputStreamReader;
  8 import java.util.ArrayList;
  9 import java.util.Scanner;
 10 
 11 public class 身分証明書 {
 12 
 13     public static 人々 findPeopleByname(String 名前) {
 14         人々 フラグ = null;
 15         for (人々 people : 人々リスト) {
 16             if(people.getName().equals(名前)) {
 17                 フラグ = people;
 18             }
 19         }
 20         return フラグ;
 21 
 22     }
 23 
 24     public static 人々 findPeopleByid(String id) {
 25         人々 フラグ = null;
 26         for (人々 people : 人々リスト) {
 27             if(people.getnumber().equals(id)) {
 28                 フラグ = people;
 29             }
 30         }
 31         return フラグ;
 32 
 33     }
 34        
 35     private static ArrayList<人々> 人々リスト; 
 36     
 37     public static void main(String[] args) {
 38         人々リスト = new ArrayList<人々>();
 39         Scanner scanner = new Scanner(System.in);
 40         File file = new File("D:\\身分証明書番号.txt");
 41         try {
 42             FileInputStream files = new FileInputStream(file);
 43             BufferedReader in = new BufferedReader(new InputStreamReader(files));
 44             String temp = null;
 45             while ((temp = in.readLine()) != null) {
 46                 
 47                 Scanner linescanner = new Scanner(temp);
 48                 linescanner.useDelimiter(" ");    
 49                 String 名前 = linescanner.next();
 50                 String 番号 = linescanner.next();
 51                 String 性別 = linescanner.next();
 52                 String 年齢 = linescanner.next();
 53                 String 出身地 = linescanner.nextLine();
 54                 人々 people = new 人々();
 55                 people.setName(名前);
 56                 people.setnumber(番号);
 57                 people.setage(年齢);
 58                 people.setsex(性別);
 59                 people.setplace(出身地);
 60                 人々リスト.add(people);
 61 
 62             }
 63         } catch (FileNotFoundException e) {
 64             System.out.println("ファイルが見つかりません");
 65             e.printStackTrace();
 66         } catch (IOException e) {
 67             System.out.println("ファイル読み取りエラー");
 68             e.printStackTrace();
 69         }
 70         boolean isTrue = true;
 71         while (isTrue) {
 72 
 73             System.out.println("***********");
 74             System.out.println("1.名前で検索");
 75             System.out.println("2.身分証明書番号で検索");
 76             System.out.println("3.終了");
 77             System.out.println("***********");
 78             int nextInt = scanner.nextInt();
 79             switch (nextInt) {
 80             case 1:
 81                 System.out.println("名前を入力してください:");
 82                 String peoplename = scanner.next();
 83                 人々 people = findPeopleByname(peoplename);
 84                 if (people != null) {
 85                     System.out.println("   名前:"+ people.getName() +
 86                                        "  身分証明書番号:"+ people.getnumber() +
 87                                        "   年齢:"+ people.getage()+
 88                                        "   性別:"+ people.getsex()+
 89                                        "   出身地:"+ people.getplace()
 90                             );
 91                 } else {
 92                     System.out.println("その人は存在しません");
 93                 }
 94                 break;
 95             case 2:
 96                 System.out.println("身分証明書番号を入力してください:");
 97                 String peopleid = scanner.next();
 98                 人々 people1 = findPeopleByid(peopleid);
 99                 if (people1 != null) {
100                     System.out.println("   名前:"+ people1.getName()+
101                                        "  身分証明書番号:"+ people1.getnumber()+
102                                        "   年齢:"+ people1.getage()+
103                                        "   性別:"+ people1.getsex()+
104                                        "   出身地:"+ people1.getplace());
105                 } else {
106                     System.out.println("その人は存在しません");
107                 }
108                 break;
109             case 3:
110                 isTrue = false;
111                 System.out.println("バイバイ!");
112                 break;
113             default:
114                 System.out.println("入力が間違っています");
115             }
116         }
117     }
118 
119 
120 }
 1 package 身分証明書;

 2 public class 人々 {
 3 
 4     private    String 名前;
 5     private    String 番号;
 6     private    String 年齢;
 7     private    String 性別;
 8     private    String 出身地;
 9 
10     public String getName()
11     {
12         return 名前;
13     }
14     public void setName(String 名前) 
15     {
16         this.名前 = 名前;
17     }
18     public String getnumber() 
19     {
20         return 番号;
21     }
22     public void setnumber(String 番号)
23     {
24         this.番号 = 番号;
25     }
26     public String getage() 
27     {
28         return 年齢;
29     }
30     public void setage(String 年齢 ) 
31     {
32         this.年齢 = 年齢;
33     }
34     public String getsex() 
35     {
36         return 性別;
37     }
38     public void setsex(String 性別 ) 
39     {
40         this.性別 = 性別;
41     }
42     public String getplace() 
43     {
44         return 出身地;
45     }
46     public void setplace(String 出身地) 
47     {
48         this.出身地 = 出身地;
49     }
50 }

実行結果は以下の通りです:

第三部分:まとめ

先生の授業での整理に基づき、この週の自主学習を通じて、継承に関する関連知識と実験スキルを習得しました。この週は祝日があったため、時間が十分にあったので、以前の学習内容と第5、6週で学んだ内容をよく結びつけ、統合しました。一歩一歩学習タスクを完了しました。実験では大きな問題はありませんでしたが、先生が課した自主実験を完成させる際、体調の問題でプログラミングを書いているときに思考論理があまり明確ではなかったため、プログラムコードは少し乱雑かもしれませんが、それでも問題の要求内容は完了しました。この一ヶ月以上のJavaの学習を通じて、プログラミング言語に対してまたより深い理解ができました。各実験後の自分の反省と先生の評価、そして先輩や同級生の指導は、私に大きな成長をもたらしてくれました。また、先生のこのような学習モデルは、私たちが最も欠いている自主学習能力をより良く養成してくれます。私たちの可塑性と持続可能性を大きく向上させてくれました。

タグ: Java 継承 抽象クラス オブジェクト指向 arraylist

7月1日 16:44 投稿