未来エンジニア養成所Blog

月単価180万以上のプログラミング講師がプログラミングを皆に楽しんでもらうための情報をお届けします。

【Java】オブジェクト指向の基本問題2-8

title


問題2-8

ピッチャーを表すPitcherクラスを作成してください。

一般的な野球選手を表現するBaseballPlayerクラスはすでに完成しています。
(変更は禁止です)

また、Pitcherクラスを使用するInheritanceBasicPracticeクラスのmainメソッドはすでに完成しています。
(変更は禁止です)


【Pitcherクラス】

  1. BaseballPlayerクラスを継承します。

  2. スーパークラスから受け継いだ3つのインスタンスフィールドのほかに、防御率を表すeraインスタンスフィールド(double型)を定義します。

  3. 引数に選手名、背番号、打率、防御率の4つの値を受け取るコンストラクタを定義します。
    そのうち、選手名、背番号、打率の3つの値は、スーパークラスのインスタンスフィールドに受け渡します。

  4. 投手の情報を紹介するintroduceインスタンスメソッドを定義します。
    出力内容は、下記実行結果を参考にしてください。


【実行結果】

選手名:山田
背番号:99
打率  :0.09
防御率:2.13


【InheritanceBasicPractice.java】

public class InheritanceBasicPractice {
    public static void main(String[] args) {

        // 投手オブジェクトの生成
        Pitcher p = new Pitcher("山田", 99, 0.09, 2.13);

        // 投手の紹介
        p.introduce();

    }
}


// 野球選手クラス
class BaseballPlayer {

    // 選手名
    protected String name;

    // 背番号
    protected int uniformNumber;

    // 打率
    protected double battingAverage;

}


// ここにPitcherクラスを作成してください


解答例

【InheritanceBasicPractice.java】

public class InheritanceBasicPractice {
    public static void main(String[] args) {

        // 投手オブジェクトの生成
        Pitcher p = new Pitcher("山田", 99, 0.09, 2.13);

        // 投手の紹介
        p.introduce();

    }
}

// 野球選手クラス
class BaseballPlayer {

    // 選手名
    protected String name;

    // 背番号
    protected int uniformNumber;

    // 打率
    protected double battingAverage;

}

// 投手クラス
class Pitcher extends BaseballPlayer {

    // 防御率
    private double era;

    // コンストラクタ
    public Pitcher(String name,
            int uniformNumber,
            double battingAverage,
            double era) {

        this.name = name;
        this.uniformNumber = uniformNumber;
        this.battingAverage = battingAverage;
        this.era = era;
    }

    // 紹介メソッド
    public void introduce() {
        System.out.println("選手名:" + name);
        System.out.println("背番号:" + uniformNumber);
        System.out.println("打率 :" + battingAverage);
        System.out.println("防御率:" + era);
    }
}


解説

オブジェクト指向言語には、3大要素というものがあります。

「カプセル化」「継承」「ポリモフィズム」の3つですが、その中でも「継承」は特に重要と言えます。



なぜ、継承は重要のでしょうか。

実は簡単には説明出来ない部分もありますが、まずは一番わかりやすい側面として「再利用性を高める」ということがあげられます。

すでに存在するリソースをできるだけ活用して、無駄を省き、効率よく開発することはとても大切です。

継承をうまく使うと、既存クラスを再利用しやすくなります。



今回は、一般的な野球選手を表現するBaseballPlayerクラスがあります。

野球選手は「選手名」「背番号」「打率」の3つの情報を保持します。

しかし、ピッチャーはそれに加えて「防御率」という情報が必要になります。

ピッチャーにだけ必要な防御率というフィールドを追加してあげる、この発想を「差分コーディング」と言います。



クラスを継承して新しいクラスを作成するには、キーワード「extends」を使用します。

// 投手クラス
class Pitcher extends BaseballPlayer {
    ....
}



こうすることで、PitcherクラスはBaseballPlayerクラスの持つフィールドやメソッドを引き継いで利用することが可能となります。

これこそが「継承」です。



くれぐれも次のようなコードを記述しないように注意してください。

// 投手クラス
class Pitcher extends BaseballPlayer {

    // 選手名
    private String name;

    // 背番号
    private int uniformNumber;

    // 打率
    private double battingAverage;

    // 防御率
    private double era;

    ....
}



やっかいなことに、これでもコンパイル・実行は可能です。

しかし、これだと何のために継承したのか分からなくなります。

せっかく受け継いだ同じ意味のフィールドを重複して定義してしまう、このミスはくれぐれも注意してください。



Javaの継承に関して、1つ捕捉しておきます。

継承されるクラスを「スーパークラス」、継承するクラスを「サブクラス」と言いますが、1つのサブクラスに対して、直接のスーパークラスは必ず1つだけです。

これを「単一継承」と言います。

プログラミング言語によっては複数のスーパークラスを持つことができる「多重継承」が可能なものもありますが、Javaは多重継承できませんのでしっかり押さえておいてください。

ちなみに、スーパークラスに、さらにスーパークラスが存在するのはOKです。

つまり、継承は階層化することも可能です。



今回は野球選手クラスの3つのフィールドのアクセス修飾子に「protected」を使用しています。

一般的にインスタンスフィールドには「private」を付加することがほとんどですが、そうするとサブクラスからスーパークラスのフィールドに直接アクセスできなくなって不便なことがあります。

「protected」は「private」より少し緩くて、サブクラスからも直接アクセスが可能になります。



最後に、継承に関して守るべきマナーをお伝えします。

確かにサブクラスは継承を行うとスーパークラスのフィールドやメソッドを簡単に受け継ぐことが可能です。

しかし、ただ受け継ぎたいだけの継承には注意が必要です。

実は、継承する際には次のような文法が成り立つことが大前提となります。


「サブクラス」は「スーパークラス」の一種である


今回だと「投手は野球選手の一種である」という文法は正しいので、正しい継承です。

「is-aの関係」と言いますが、もし継承していいか迷ったときは、判断基準の1つにしてください。


参考図書



LINE公式アカウント

仕事が辛くてたまらない人生が、仕事が楽しくてたまらない人生に変わります。
【登録いただいた人全員に、無料キャリア相談プレゼント中!】


LineOfficial

友だち追加