継承
継承は、インヘリタンスとも呼ばれます。既に用意されているオブジェクトを基に、機能などを追加して新たなオブジェクトを作ることができる機能です。継承することにより、既に用意されているクラスに手を加えて、新しいクラスを作成することができます。
これから、Busクラスを作成してみましょう。バスは、人を乗せて運ぶことができますが、車と同じように進んだり、止まったりすることができます。つまり、Carクラスのような機能を持っています。「バスは車である」ということができます。このような関係を「is-a」の関係といいます(Bus is a Car)。
このような場合、BusクラスはCarクラスの機能等を引き継いで作成することができます。Carクラスを継承してBusクラスを作ることができます。このようにすることで、Busにしかない属性、機能を記述すればよくなります。つまり、CarクラスとBusクラスの差分を記述するわけです。
継承において、もとになるクラスをスーパークラスや基底クラスといい、それをもとに新しく作成するクラスをサブクラスや派生クラスといいます。
クラス継承の書式 |
---|
class サブクラス名 extends スーパークラス名{ 各種定義… } |
継承の指定をした後、スーパークラスにはないフィールドやメソッドを追加や修正する記述をします。
○ ファイル
次のようにファイルを作成してください。
ファイル名 | Bus.java |
---|
○ プログラム
作成したファイルに、次のように記述してください。
Bus.java
- public class Bus extends Car{
- //フィールド
- private int salesAmount; //運賃
- private int passengerNumber; //乗客人数
- //コンストラクター
- public Bus(){
- this(100);
- }
- public Bus(double gas){
- super(gas);
- this.salesAmount = 0;
- this.passengerNumber = 0;
- }
- //メソッド
- //乗車させるメソッド
- public String rideToBus(int fare){
- //走行中かどうか
- if(this.getSpeed() != 0){
- return "停車してください。";
- }
- //満席かどうか
- if(this.passengerNumber >= 50){
- return "満席のため、乗車できません。";
- }
- //料金と、乗車人数を加算
- this.salesAmount += fare;
- this.passengerNumber++;
- return null;
- }
- //降車させるメソッド
- public String getOffBus(){
- //走行中かどうか
- if(this.getSpeed() != 0){
- return "停車してください。";
- }
- //乗客がいるかどうか
- if(this.passengerNumber == 0){
- return "乗客はいません。";
- }
- //乗車人数を減算
- this.passengerNumber--;
- return null;
- }
- //フィールドのgetterの準備
- public int getSalesAmount(){
- return this.salesAmount;
- }
- public int getPassengerNumber(){
- return this.passengerNumber;
- }
- }
○ クラス図
○ 解説
1行目では、「extends」を指定してCarクラスを継承しています。これにより、Carクラスが持っているspeedUpメソッドやspeedDownメソッドなどが使えるようになります。
3行目のフィールド変数は売上金額を扱います。乗客が乗車するたびに加算されていきます。このフィールドはprivate修飾子がついているので、設定はクラス内部からしかできないようになっています。値を取得するには54行目から定義されている「getSalesAmount」メソッドを利用します。4行目のフィールド変数は現在の乗客数を扱います。今回は50人まで乗せられるようにプログラムで制御しています。このフィールドも設定はクラス内部からしかできないようになっています。取得するには58行目から定義されている「getPassengerNumber」メソッドを利用します。
7~9行目ではコンストラクターを定義しています。このコンストラクターは引数なしで呼ばれると、オーバーロードしているガソリン量を受け取るコンストラクターを呼び出します。11~15行目では、ガソリン量を受け取るコンストラクターを定義しています。12行目はスーパークラスのコンストラクターを呼び出しています。「super」キーワードは、スーパークラスを表します。ここでのsuperキーワードはスーパークラスであるCarクラスを表します。
19~34行目は、乗車するメソッドです。このメソッドは運賃を受け取り、乗車処理をします。その際、バスが走っていたり、乗客数が満員になっていたりすると乗車できないようにしています。いずれにも当てはまらない場合は、受け取った運賃を売上金額フィールドに加算し、乗客数フィールドを1人分増やします。
37~51行目は、降車するメソッドです。バスが走っていたり、乗客がいなかったりした場合は降車できないようにしています。いずれにも当てはまらない場合は、乗客数フィールドを1人分減らします。
○ ファイル
CarTest.javaをコピーして、次のようにファイルを作成してください。
ファイル名 | BusTest.java |
---|
○ プログラム
次のようにプログラムを記述してください。
BusTest.java
- public class BusTest{
- //車の状態を表示するメソッド
- public static void showData(Bus bus){
- System.out.println("スピード:" + bus.getSpeed() + "km");
- System.out.println("ガソリン:" + bus.getGas() + "L");
- System.out.println("売上金額:" + bus.getSalesAmount() + "円");
- System.out.println("乗車人数:" + bus.getPassengerNumber() + "人");
- }
- public static void main(String[] args) throws Exception{
- //インスタンスを生成する
- Bus bus = new Bus(150);
- //現在の状態を表示する
- showData(bus);
- //キーボード入力の準備をする
- BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
- while(true){
- //操作を入力
- System.out.print("1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:");
- String inputdata = br.readLine();
- //操作によって分岐する
- switch (inputdata){
- case "1":
- //加速する
- bus.speedUp(5);
- showData(bus);
- break;
- case "2":
- //減速する
- bus.speedDown(5);
- showData(bus);
- break;
- case "3":
- //給油する
- bus.setGas(80);
- showData(bus);
- break;
- case "7":
- //乗車する
- String retgetoff = bus.rideToBus(200);
- if(retgetoff == null){
- showData(bus);
- }else{
- System.out.println(retgetoff);
- }
- break;
- case "8":
- //降車する
- String retride = bus.getOffBus();
- if(retride == null){
- showData(bus);
- }else{
- System.out.println(retride);
- }
- break;
- case "9":
- //プログラムを終了する
- return;
- }
- }
- }
- }
○ コンパイルと実行
C:¥work>javac BusTest.java
C:¥work>java BusTest
スピード:0km
ガソリン:150.0L
売上金額:0円
乗車人数:0人
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:1
スピード:5km
ガソリン:149.5L
売上金額:0円
乗車人数:0人
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:7
停車してください。
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:2
スピード:0km
ガソリン:149.5L
売上金額:0円
乗車人数:0人
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:7
スピード:0km
ガソリン:149.5L
売上金額:200円
乗車人数:1人
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:1
スピード:5km
ガソリン:149.0L
売上金額:200円
乗車人数:1人
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:8
停車してください。
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:2
スピード:0km
ガソリン:149.0L
売上金額:200円
乗車人数:1人
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:8
スピード:0km
ガソリン:149.0L
売上金額:200円
乗車人数:0人
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:8
乗客はいません。
1)加速 2)減速 3)給油 7)乗車 8)降車 9)終了:9
C:¥work>
○ 解説
14行目では、Busオブジェクトを生成しています。BusオブジェクトはCarクラスを継承しているので今まで通り加速したり、減速したりできます。
46行目では、乗車メソッドを呼び出しています。戻り値がnullでない場合はエラーメッセージが返って来ているので、コンソールに表示しています。
55行目では、降車メソッドを呼び出しています。このメソッドは乗車メソッドと同様にエラーメッセージかnullが返ってくるのでそれに応じた処理をしています。
今回はCarクラスを基にBusクラスを作成しました。BusクラスはCarクラスを継承しているので、Carクラスのメンバーを記述しなくても使用することができます。ただし、privateになっているメンバーは、継承したクラスでも直接アクセスすることができません。「protected」にすれば、直接操作できます。「protected」は、継承関係であればアクセスできますが、外部クラスからはアクセスすることができません。 Javaでは、サブクラスは1つのクラスから継承することができます。複数のクラスから継承させることはできません。(多重継承の禁止)
Busクラスのインスタンスを生成するときにBusクラスのコンストラクターを呼び出します。すると、初めにスーパークラスであるCarクラスのコンストラクターを呼び出します。サブクラスのコンストラクターでスーパークラスのコンストラクターの呼び出しが特に記述されていない場合、スーパークラスのデフォルトコンストラクターが呼び出されます。もし、スーパークラスで引数を持つコンストラクターが定義されていると、デフォルトコンストラクターは仮定されないので、サブクラスでスーパークラスのコンストラクターの呼び出しを記述しなければなりません。