Java - クラスの継承


■ページ目次

Top

■クラスの継承

Top
■商品クラスの継承
  1. 上記"Product.java"を継承して、割引価格を追加したクラス"DiscountProduct.java"を作成してください。
    1. // 1011
    2. // 割引商品クラスです。
    3. // ひとつの商品に対するフィールドやフィールドを操作するためのメソッドを
    4. // 提供しています。
    5. public class DiscountProduct extends Product {
    6. private int discount; // 商品割引率
    7. // 割引商品クラスのコンストラクター。
    8. DiscountProduct(String code, String name, int price) {
    9. setCode(code);
    10. setName(name);
    11. setPrice(price);
    12. setDiscount(0);
    13. }
    14. // 割引商品クラスのコンストラクター。
    15. DiscountProduct(String code, String name, String price) {
    16. setCode(code);
    17. setName(name);
    18. setPrice(price);
    19. setDiscount(0);
    20. }
    21. // 割引商品クラスのコンストラクター。
    22. DiscountProduct(String code, String name, int price, int discount) {
    23. setCode(code);
    24. setName(name);
    25. setPrice(price);
    26. setDiscount(discount);
    27. }
    28. // 割引商品クラスのコンストラクター。
    29. DiscountProduct(String code, String name, String price, String discount) {
    30. setCode(code);
    31. setName(name);
    32. setPrice(price);
    33. setDiscount(discount);
    34. }
    35. // 商品割引率に値を設定します。
    36. void setDiscount(int discount) {
    37. if (discount < 0 || discount > 100) {
    38. this.discount = 0;
    39. return;
    40. }
    41. this.discount = discount;
    42. }
    43. // 商品割引率に値を設定します。
    44. void setDiscount(String discount) {
    45. setDiscount(Integer.parseInt(discount));
    46. }
    47. // 商品割引率の値を取得します。
    48. int getDiscount() {
    49. return this.discount;
    50. }
    51. }
    $ java TestProduct
    DiscountProduct.java:7: シンボルを解決できません。
    シンボル: コンストラクタ Product ()
    場所    : Product の クラス
        DiscountProduct(String code, String name, int price) {
                                                             ^
    DiscountProduct.java:15: シンボルを解決できません。
    シンボル: コンストラクタ Product ()
    場所    : Product の クラス
        DiscountProduct(String code, String name, String price) {
                                                                ^
    DiscountProduct.java:23: シンボルを解決できません。
    シンボル: コンストラクタ Product ()
    場所    : Product の クラス
        DiscountProduct(String code, String name, int price, int discount) {
                                                                           ^
    DiscountProduct.java:31: シンボルを解決できません。
    シンボル: コンストラクタ Product ()
    場所    : Product の クラス
        DiscountProduct(String code, String name, String price, String discount) {
                                                                                 ^
    エラー 4 個
    
■引数なしのコンストラクター
商品クラスに引数なしのコンストラクターを加える
  1. 上記"Product.java"に、引数なしのコンストラクターを追加したクラス"Product.java"を作成してください。
    1. // 1012
    2. // 商品クラスです。
    3. // ひとつの商品に対するフィールドやフィールドを操作するためのメソッドを
    4. // 提供しています。
    5. public class Product {
    6. private String code; // 商品コード
    7. private String name; // 商品名
    8. private int price; // 商品定価
    9. // 商品クラスのコンストラクター。
    10. Product() {
    11. }
    12. // 商品クラスのコンストラクター。
    13. Product(String code, String name, int price) {
    14. setCode(code);
    15. setName(name);
    16. setPrice(price);
    17. }
    18. // 商品クラスのコンストラクター。
    19. Product(String code, String name, String price) {
    20. setCode(code);
    21. setName(name);
    22. setPrice(price);
    23. }
    24. // 商品コードに値を設定します。
    25. void setCode(String code) {
    26. this.code = code;
    27. }
    28. // 商品コードの値を取得します。
    29. String getCode() {
    30. return this.code;
    31. }
    32. // 商品名に値を設定します。
    33. void setName(String name) {
    34. this.name = name;
    35. }
    36. // 商品名の値を取得します。
    37. String getName() {
    38. return this.name;
    39. }
    40. // 商品定価に値を設定します。
    41. void setPrice(int price) {
    42. if (price < 0) {
    43. this.price = 0;
    44. return;
    45. }
    46. this.price = price;
    47. }
    48. // 商品定価に値を設定します。
    49. void setPrice(String price) {
    50. setPrice(Integer.parseInt(price));
    51. }
    52. // 商品定価の値を取得します。
    53. int getPrice() {
    54. return this.price;
    55. }
    56. }
  2. 以下の"TestProduct.java"を入力してコンパイル・実行してください。
    1. // 1012 = 1011
    2. // 割引商品クラスをテストするクラスです。
    3. public class TestProduct {
    4. public static void main(String[] args) {
    5. DiscountProduct p1 = new DiscountProduct("A001", "パソコン", 188000, 20);
    6. System.out.println("割引商品のインスタンスを生成しました。 p1 = " + p1);
    7. System.out.println(" code = " + p1.getCode());
    8. System.out.println(" name = " + p1.getName());
    9. System.out.println(" price = " + p1.getPrice());
    10. System.out.println(" discount = " + p1.getDiscount());
    11. DiscountProduct p2 = new DiscountProduct("P001", "プリンター", 24000);
    12. System.out.println("割引商品のインスタンスを生成しました。 p2 = " + p2);
    13. System.out.println(" code = " + p2.getCode());
    14. System.out.println(" name = " + p2.getName());
    15. System.out.println(" price = " + p2.getPrice());
    16. System.out.println(" discount = " + p2.getDiscount());
    17. }
    18. }

    □ 実行結果

    $ java TestProduct
    割引商品のインスタンスを生成しました。 p1 = DiscountProduct@15ff48b
          code = A001
          name = パソコン
         price = 188000
      discount = 20
    割引商品のインスタンスを生成しました。 p2 = DiscountProduct@affc70
          code = P001
          name = プリンター
         price = 24000
      discount = 0
    

Top

■this()とsuper()


Top

■this変数とsuper変数

Top
割引商品クラスを this() と super() を使って再構成します
  1. 上記"Product.java"を継承して、割引価格を追加したクラス"DiscountProduct.java"を作成してください。
    1. // 1013
    2. // 割引商品クラスです。
    3. // ひとつの商品に対するフィールドやフィールドを操作するためのメソッドを
    4. // 提供しています。
    5. public class DiscountProduct extends Product {
    6. private int discount; // 商品割引率
    7. // 割引商品クラスのコンストラクター。
    8. DiscountProduct(String code, String name, int price) {
    9. this(code, name, price, 0);
    10. }
    11. // 割引商品クラスのコンストラクター。
    12. DiscountProduct(String code, String name, String price) {
    13. this(code, name, price, "0");
    14. }
    15. // 割引商品クラスのコンストラクター。
    16. DiscountProduct(String code, String name, int price, int discount) {
    17. super(code, name, price);
    18. setDiscount(discount);
    19. }
    20. // 割引商品クラスのコンストラクター。
    21. DiscountProduct(String code, String name, String price, String discount) {
    22. super(code, name, price);
    23. setDiscount(discount);
    24. }
    25. // 商品割引率に値を設定します。
    26. void setDiscount(int discount) {
    27. if (discount < 0 || discount > 100) {
    28. this.discount = 0;
    29. return;
    30. }
    31. this.discount = discount;
    32. }
    33. // 商品割引率に値を設定します。
    34. void setDiscount(String discount) {
    35. setDiscount(Integer.parseInt(discount));
    36. }
    37. // 商品割引率の値を取得します。
    38. int getDiscount() {
    39. return this.discount;
    40. }
    41. }

    □ 実行結果

    $ java TestProduct
    割引商品のインスタンスを生成しました。 p1 = DiscountProduct@15ff48b
          code = A001
          name = パソコン
         price = 188000
      discount = 20
    割引商品のインスタンスを生成しました。 p2 = DiscountProduct@affc70
          code = P001
          name = プリンター
         price = 24000
      discount = 0
    
  2. この再構築により、上記"Product.java"には、ふたたび引数なしのコンストラクターは必要なくなります。("Product.java")
    1. // 1013
    2. // 商品クラスです。
    3. // ひとつの商品に対するフィールドやフィールドを操作するためのメソッドを
    4. // 提供しています。
    5. public class Product {
    6. private String code; // 商品コード
    7. private String name; // 商品名
    8. private int price; // 商品定価
    9. // 商品クラスのコンストラクター。
    10. Product() {
    11. }
    12. :
    13. }

Top
■(参考) 3階層の継承
Top

■すべてのクラスのスーパークラス(java.lang.Object)


■メソッドのオーバーライドとフィールドの隠蔽

Top
■getPrice()メソッドのオーバーライド
  1. 上記"DiscountProduct.java"のgetPrice()メソッドをオーバーライドして、割引後の価格が戻るようにしてください。("DiscountProduct.java")
    1. // 1014
    2. // 割引商品クラスです。
    3. // ひとつの商品に対するフィールドやフィールドを操作するためのメソッドを
    4. // 提供しています。
    5. public class DiscountProduct extends Product {
    6. private int discount; // 商品割引率
    7. :
    8. // 商品の売値の値を取得します。
    9. int getPrice() {
    10. return (int)(super.getPrice() * (1 - discount / 100.0));
    11. }
    12. }
    $ java TestProduct
    割引商品のインスタンスを生成しました。 p1 = DiscountProduct@15ff48b
          code = A001
          name = パソコン
         price = 150400
      discount = 20
    

Top
■継承関係にある参照変数への代入
Top
■継承時の注意点
Top
■(参考)継承時のフィールドとメソッドの振舞い
Top

■クラス型の配列

■例題
  1. 下記"TestProduct.java"を作成、実行してください。
    1. // 1015
    2. // 商品クラスをテストするクラスです。
    3. public class TestProduct {
    4. public static void main(String[] args) {
    5. Product[] p = new Product[4];
    6. p[0] = new Product("A001", "パソコン", 188000);
    7. p[1] = new Product("P001", "プリンター", 24000);
    8. p[2] = new Product("C001", "CD-ROM", 6500);
    9. p[3] = new Product("M001", "USBメモリー", 9800);
    10. System.out.println("商品配列のインスタンスを生成しました。 p = " + p);
    11. for (int i = 0; i < p.length; i++) {
    12. System.out.println("商品のインスタンスを生成しました。 p[" + i + "] = " + p[i]);
    13. System.out.println(" code = " + p[i].getCode());
    14. System.out.println(" name = " + p[i].getName());
    15. System.out.println(" price = " + p[i].getPrice());
    16. }
    17. }
    18. }

    □ 実行結果

    $ java TestProduct
    商品配列のインスタンスを生成しました。 p = [LProduct;@131f71a
    商品のインスタンスを生成しました。 p[0] = Product@15601ea
       code = A001
       name = パソコン
      price = 188000
    商品のインスタンスを生成しました。 p[1] = Product@197d257
       code = P001
       name = プリンター
      price = 24000
    商品のインスタンスを生成しました。 p[2] = Product@7259da
       code = C001
       name = CD-ROM
      price = 6500
    商品のインスタンスを生成しました。 p[3] = Product@16930e2
       code = M001
       name = USBメモリー
      price = 9800
    
Top
■実習
Top

■多態性

  1. 下記"TestProduct.java"を作成、実行してください。
    1. // 1016
    2. // 商品クラスをテストするクラスです。
    3. public class TestProduct {
    4. public static void main(String[] args) {
    5. Product[] p = new Product[4];
    6. p[0] = new DiscountProduct("A001", "パソコン", 188000, 20);
    7. p[1] = new Product("P001", "プリンター", 24000);
    8. p[2] = new DiscountProduct("C001", "CD-ROM", 6500, 10);
    9. p[3] = new Product("M001", "USBメモリー", 9800);
    10. System.out.println("商品配列のインスタンスを生成しました。 p = " + p);
    11. for (int i = 0; i < p.length; i++) {
    12. System.out.println("商品のインスタンスを生成しました。 p[" + i + "] = " + p[i]);
    13. System.out.println(" code = " + p[i].getCode());
    14. System.out.println(" name = " + p[i].getName());
    15. System.out.println(" price = " + p[i].getPrice());
    16. }
    17. }
    18. }

    □ 実行結果

    $ java TestProduct
    商品配列のインスタンスを生成しました。 p = [LProduct;@15ff48b
    商品のインスタンスを生成しました。 p[0] = DiscountProduct@affc70
       code = A001
       name = パソコン
      price = 150400
    商品のインスタンスを生成しました。 p[1] = Product@1e63e3d
       code = P001
       name = プリンター
      price = 24000
    商品のインスタンスを生成しました。 p[2] = DiscountProduct@1004901
       code = C001
       name = CD-ROM
      price = 5850
    商品のインスタンスを生成しました。 p[3] = Product@1b90b39
       code = M001
       name = USBメモリー
      price = 9800
    
Top
■実習

  1. 本(Book)クラスを継承して、シリーズ名(String)と通番(int)を持つクラスSeriesBook.javaと、発行日時(date)を持つクラスMagazine.javaを作成してください。

    Book.java

    1. public class Book {
    2. private String title; // 書名
    3. private String author; // 著作者
    4. // コンストラクター
    5. public Book(String title, String author) {
    6. setTitle(title);
    7. setAuthor(author);
    8. }
    9. // title のゲッター
    10. public String getTitle() {
    11. return this.title;
    12. }
    13. // author のゲッター
    14. public String getAuthor() {
    15. return this.author;
    16. }
    17. // title のセッター
    18. public void setTitle(String title) {
    19. this.title = title;
    20. }
    21. // author のセッター
    22. public void setAuthor(String author) {
    23. this.author = author;
    24. }
    25. }

    SeriesBook.java

    1. public class SeriesBook extends Book {
    2. // コードを記述してください。
    3. }

    Magazine.java

    1. public class Magazine extends Book {
    2. // コードを記述してください。
    3. }

    SeriesBook.javaクラス、Magazine.java クラスをテストするアプリケーションBookTest.java

    1. public class BookTest {
    2. public static void main(String[] args) {
    3. Book b1 = new Book(args[0], args[1]);
    4. System.out.println("Book1 = [" + b1.getTitle() + ", " + b1.getAuthor() + "]");
    5. SeriesBook b2 = new SeriesBook(args[0], args[1], args[2], Integer.parseInt(args[3]));
    6. System.out.print("Book2 = [" + b2.getTitle() + ", " + b2.getAuthor());
    7. System.out.println(", " + b2.getSeries() + ", " + b2.getVolume() + "]");
    8. Magazine b3 = new Magazine(args[0], args[1], new java.util.Date().toString()(*));
    9. System.out.print("Book3 = [" + b3.getTitle() + ", " + b3.getAuthor());
    10. System.out.println(", " + b3.getDate() + "]");
    11. }
    12. }
    (*) new java.util.Date().toString() は、現在日時の文字列表現をあらわします。

    □ 実行結果

    $ java BookTest JavaBook Maruno Java 3
    Book1 = [JavaBook, Maruno]
    Book2 = [JavaBook, Maruno, Java, 3]
    Book3 = [JavaBook, Maruno, Wed Jun 22 21:28:12 JST 2005]
    

  2. 上記クラスSeriesBook.javaと、クラスMagazine.javaで、getTitle() メソッドの戻り値をつぎのようになるようにオーバーライドしてください。(SeriesBook.java, Magazine.java)。
      SeriesBook.java ... "シリーズ名 - 書名 (通番)"
      Magazine.java   ... "書名 (日付)"
    

    □ 実行結果

    $ java BookTest JavaBook Maruno Java 3
    Book1 = [JavaBook, Maruno]
    Book2 = [JavaBasic - JavaBook (3), Maruno, JavaBasic, 3]
    Book3 = [JavaBook (Thu Jun 23 12:41:09 JST 2005), Maruno, Thu Jun 23 12:41:09 JST 2005]
    

    □ テストするアプリケーションBookTest.java

    1. public class BookTest {
    2. public static void main(String[] args) {
    3. Book b1 = new Book(args[0], args[1]);
    4. System.out.println("Book1 = " + b1.getTitle());
    5. Book b2 = new SeriesBook(args[0], args[1], args[2], Integer.parseInt(args[3]));
    6. System.out.println("Book2 = " + b2.getTitle());
    7. Book b3 = new Magazine(args[0], args[1], new java.util.Date().toString());
    8. System.out.println("Book3 = " + b3.getTitle());
    9. }
    10. }

    □ 実行結果

    $ java BookTest JavaBook Maruno Java 3
    Book1 = JavaBook
    Book2 = Java - JavaBook (3)
    Book3 = JavaBook (Thu Jun 23 12:36:17 JST 2005)
    T 2005]
    
  3. つぎの図形クラス"Zukei.java"があります。

    図形クラス階層
    図 図形クラス階層

    1. public class Zukei {
    2. private String name; // 名前
    3. String getName() { // 名前の取得
    4. return name;
    5. }
    6. void setName(String name) { // 名前の設定
    7. this.name = name;
    8. }
    9. double length() { // 周の長さ
    10. return 0.0;
    11. }
    12. }
    この図形クラスを継承して円、三角形、四角形の図形を処理するクラスを作ります。コンストラクターはつぎのとおりです。なお、図形の座標の原点は左上にあるものとします。
  4. "Maru.java"
  5. Maru(String name, int x, int y, int r) 中心(x, y)と半径r
    Maru(int x, int y, int r) 中心(x, y)と半径r
  6. "Sankaku.java"
  7. Sankaku(String name, int[][] p) 頂点の座標(x0, y0),(x1, y1), (x2, y2)の組
    Sankaku(int[][] p) 頂点の座標(x0, y0),(x1, y1), (x2, y2)の組
  8. "Shikaku.java"
  9. Shikaku(String name, int x0, int y0, int x1, int y1) 左上の座標(x0, y0)と右下の座標(x1, y1)
    Shikaku(int x0, int y0, int x1, int y1) 左上の座標(x0, y0)と右下の座標(x1, y1)

    また、図形の周の長さを戻すメソッドlength()をオーバーライドしてください。周の長さは、つぎの式によります。Math.PIは、Mathクラスのdouble型定数で、円周率をあらわします。

    なお、これらをテストするアプリケーション"ZukeiTest01.java"と、三角形クラス"Sankaku.java"のサンプル・ソース・ファイルをつけます。

    "ZukeiTest01.java"

    1. public class ZukeiTest01 {
    2. static Zukei[] z;
    3. ZukeiTest01() {
    4. z = new Zukei[] {
    5. new Shikaku("基準四角", 0, 0, 100, 100)
    6. , new Sankaku("基準三角", new int[][]{{0, 0}, {0, 100}, {100, 0}})
    7. , new Maru("基準丸", 0, 0, 100)
    8. , new Sankaku(new int[][]{{100, 100}, {10, 250}, {300, 300}})
    9. , new Maru(150, 170, 60)
    10. , new Shikaku(120, 130, 300, 190)
    11. };
    12. }
    13. public static void main(String[] args) {
    14. ZukeiTest01 zt = new ZukeiTest01();
    15. for (int i = 0; i < z.length; i++) {
    16. System.out.println(z[i].getName() + " の周の長さ = " + Math.round(z[i].length()));
    17. }
    18. }
    19. }

    "Maru.java"

    1. public class Maru extends Zukei {
    2. private int x0, y0; // 中心
    3. private int r; // 半径
    4. Maru(String name, int x0, int y0, int r) {
    5. setName(name);
    6. this.x0 = x0;
    7. this.y0 = y0;
    8. this.r = r;
    9. }
    10. Maru(int x0, int y0, int r) {
    11. this("丸", x0, y0, r);
    12. }
    13. double length() { // 周の長さ
    14. // ここにコードを記述してください。
    15. }
    16. }

    "Sankaku.java"

    1. public class Sankaku extends Zukei {
    2. private int[][] p; // 頂点
    3. private double[] l = new double[3]; // 辺の長さ
    4. Sankaku(int[][] p) {
    5. this("三角形", p);
    6. }
    7. Sankaku(String name, int[][] p) {
    8. setName(name);
    9. this.p = p;
    10. for (int i = 0; i < l.length; i++) {
    11. l[i] = distance(p[i], p[(i + 1) % l.length]);
    12. }
    13. }
    14. double length() { // 周の長さ
    15. return sum(l);
    16. }
    17. private double sum(double[] x) { // 要素値の合計
    18. double s = 0;
    19. for (int i = 0; i < l.length; i++) {
    20. s += l[i];
    21. }
    22. return s;
    23. }
    24. private double distance(int[] x, int[] y) { // 頂点間の距離
    25. return Math.sqrt(sq(diff(x[0], y[0])) + sq(diff(x[1], y[1])));
    26. }
    27. private int sq(int x) { // 2乗
    28. return x * x;
    29. }
    30. private int diff(int x, int y) { // 差
    31. return Math.abs(y - x);
    32. }
    33. }

    "Shikaku.java"

    1. public class Shikaku extends Zukei {
    2. private int x0, y0; // 左上の頂点の座標
    3. private int x1, y1; // 左上の頂点の座標
    4. private int w, h; // 幅と高さ
    5. Shikaku(String name, int x0, int y0, int x1, int y1) { // コンストラクター
    6. setName(name);
    7. this.x0 = x0;
    8. this.y0 = y0;
    9. this.x1 = x1;
    10. this.y1 = y1;
    11. w = Math.abs(x0 - x1);
    12. h = Math.abs(y0 - y1);
    13. }
    14. Shikaku(int x0, int y0, int x1, int y1) { // コンストラクター
    15. this("四角形", x0, y0, x1, y1);
    16. }
    17. double length() { // 周の長さ
    18. // ここにコードを記述してください。
    19. }
    20. }

    □ 実行結果

    $ java ZukeiTest01
    基準四角 の周の長さ = 400
    基準三角 の周の長さ = 341
    基準丸 の周の長さ = 628
    三角形 の周の長さ = 752
    丸 の周の長さ = 377
    四角形 の周の長さ = 480
    
Top

inserted by FC2 system