0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Java入門】第10章 継承とインターフェース

0
Last updated at Posted at 2026-10-31

あるクラスのフィールドとメソッドを引き継いで、新しいクラスを作ることを 継承 といいます。また、「このメソッドを持つ」という約束だけを決めたものが インターフェース です。Spring入門では、Form クラスの継承、Repository のインターフェース、Serializable のように、この章の書き方が何度も出てきます。

この章で学ぶこと

  • extends による継承
  • メソッドの上書き(オーバーライド)と @Override
  • すべてのクラスの親 Object と toString()
  • interface の定義と implements
  • Serializable と serialVersionUID

10.1 この章で作るもの

この章では、ch10 パッケージに、社員のクラス Employee、それを継承した管理者のクラス Manager、インターフェース Validatable、そして Main を作ります。章の最後には、Main を実行するとコンソールに次のように表示されるようになります。

コンソール
雷禅 海皇(26歳)
院照 心愛(27歳)総務部の管理者
雷禅 海皇 の年齢は正しい:true
院照 心愛 の年齢は正しい:true
ファイル 作業 内容
ch10/Employee.java 新規 社員を表すクラス(第9章と同じ形)
ch10/Manager.java 新規 Employee を継承した、管理者を表すクラス
ch10/Validatable.java 新規 「正しい値かを調べられる」ことを表すインターフェース
ch10/Main.java 新規 これらを使うクラス(main あり)

10.2 継承

管理者は、社員の一種です。名前と年齢を持ち、さらに「管理する部署」を持ちます。Employee クラスを書き写さずに、「Employee のすべてを引き継いで、部署を足す」のが継承です。

  1. src を右クリックし、新規 → パッケージ で ch10 パッケージを作ります。

  2. ch10 パッケージを右クリックし、新規 → クラス で、名前 Employee、main の チェックを入れずに クラスを作ります。第9章と同じ内容を入力します(getter と setter は ソース → getter および setter の生成 で作れます)。

    ch10/Employee.java
    package ch10;
    
    /** 社員を表す */
    public class Employee {
    
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
    }
    
  3. ch10 パッケージを右クリックし、新規 → クラス で、名前 Manager と入力します。「スーパークラス」の欄が java.lang.Object になっているので、ch10.Employee に書き換えて、main の チェックを入れずに「完了」をクリックします。

    新規 Java クラスの画面。名前に Manager、スーパークラスに ch10.Employee
    図10-1 スーパークラスに ch10.Employee と入力(赤枠)

    public class Manager extends Employee { と書かれたクラスができます。「スーパークラス」の欄に書く代わりに、自分で extends Employee と入力してもかまいません。

  4. 緑の行を入力します(getter と setter は生成で作れます)。

    ch10/Manager.java
    package ch10;
    
    /** 管理者を表す。社員の情報に加えて、管理する部署を持つ */
    public class Manager extends Employee {
    
        private String deptName;
    
        public String getDeptName() {
            return deptName;
        }
    
        public void setDeptName(String deptName) {
            this.deptName = deptName;
        }
    
    }
    
  5. ch10 パッケージを右クリックし、新規 → クラス で、名前 Main、main に チェックを入れて クラスを作り、緑の行を入力します。

    ch10/Main.java
    package ch10;
    
    public class Main {
    
        public static void main(String[] args) {
            Employee e1 = new Employee();
            e1.setName("雷禅 海皇");
            e1.setAge(26);
            Manager m1 = new Manager();
            m1.setName("院照 心愛");
            m1.setAge(27);
            m1.setDeptName("総務部");
            System.out.println(e1.getName() + "(" + e1.getAge() + "歳)");
            System.out.println(m1.getName() + "(" + m1.getAge() + "歳)" + m1.getDeptName() + "の管理者");
        }
    
    }
    
  6. 保存して、Main.java を実行します。

    コンソール
    雷禅 海皇(26歳)
    院照 心愛(27歳)総務部の管理者
    

Manager クラスには setName も getAge も書いていませんが、m1.setName(…) や m1.getAge() が使えています。extends Employee によって、Employee のフィールドとメソッドを引き継いでいるからです。

用語 意味 例
継承 あるクラスのフィールドとメソッドを引き継いで、新しいクラスを作ること。class 新しいクラス extends 元のクラス と書く class Manager extends Employee
親クラス(スーパークラス) 引き継がれる元のクラス Employee
子クラス(サブクラス) 引き継いで作った新しいクラス。親のすべてに、自分のフィールドやメソッドを足せる Manager

子クラスのオブジェクトは、親クラスの型の変数にも入れられます。Employee e = new Manager(); と書けます(管理者は社員の一種なので)。逆の Manager m = new Employee(); はエラーになります。

【知識メモ】Spring入門での継承

Spring入門では、社員登録の入力フォーム RegisterForm を継承して、社員変更の入力フォーム UpdateForm extends RegisterForm を作ります。変更のフォームは、登録のフォームの項目に社員IDを足しただけなので、継承で書くと項目を2度書かずに済みます。

【知識メモ】private なフィールドと継承

Employee の name は private なので、子クラスの Manager の中でも name と直接は書けません。getName() を通して読みます。private は「同じクラスの中だけ」であり、子クラスは別のクラスだからです。

10.3 オーバーライドと toString

すべてのクラスの親 Object

extends を書いていない Employee クラスも、実は Object というクラスを継承しています。Object は Java のすべてのクラスの親で、どのクラスも Object のメソッドを引き継いでいます。その1つが、オブジェクトを文字列にする toString() です。

  1. Main.java の main メソッドの最後に、緑の行を書き足します。

    ch10/Main.java(main メソッドの最後)
            System.out.println(m1.getName() + "(" + m1.getAge() + "歳)" + m1.getDeptName() + "の管理者");
            System.out.println(e1);
        }
    
  2. 保存して実行します。最後に、次のような行が表示されます(@ の後ろの文字は、環境によって変わります)。

    コンソール(最後の行)
    ch10.Employee@6d06d69c
    

println にオブジェクトを渡すと、そのオブジェクトの toString() が呼ばれ、返ってきた文字列が表示されます。Object の toString() は「クラス名@ハッシュコード(16進形式)」という形の文字列を返すので、このような表示になりました。

オーバーライド

親クラスから引き継いだメソッドを、子クラスで書き直すことを オーバーライド といいます。Employee で toString() をオーバーライドして、名前と年齢を返すようにしてみましょう。

  1. Employee.java の最後(setAge の後ろ)に、緑の行を書き足します。

    ch10/Employee.java(クラスの最後)
        public void setAge(int age) {
            this.age = age;
        }
    
        /** 一覧やログに出すために、名前と年齢を1行の文字列にする */
        @Override
        public String toString() {
            return name + "(" + age + "歳)";
        }
    
    }
    
  2. Manager.java の最後にも、緑の行を書き足します。

    ch10/Manager.java(クラスの最後)
        public void setDeptName(String deptName) {
            this.deptName = deptName;
        }
    
        /** 社員の表示に、管理する部署を付け足す */
        @Override
        public String toString() {
            return getName() + "(" + getAge() + "歳)" + deptName + "の管理者";
        }
    
    }
    
  3. Main.java の表示の3行を、緑の行のように書き換えます。

    ch10/Main.java
    package ch10;
    
    public class Main {
    
        public static void main(String[] args) {
            Employee e1 = new Employee();
            e1.setName("雷禅 海皇");
            e1.setAge(26);
            Manager m1 = new Manager();
            m1.setName("院照 心愛");
            m1.setAge(27);
            m1.setDeptName("総務部");
            System.out.println(e1);
            System.out.println(m1);
        }
    
    }
    
  4. 保存して実行します。

    コンソール
    雷禅 海皇(26歳)
    院照 心愛(27歳)総務部の管理者
    

println(e1) では Employee の toString() が、println(m1) では Manager の toString() が呼ばれています。オブジェクトの実際のクラスのメソッドが使われるので、子クラスで書き直せば、その内容に変わります。

@Override

オーバーライドするメソッドの上には @Override を付けます。@ で始まるこの印を アノテーション といいます(第13章で詳しく学びます)。@Override は、「このメソッドは親のメソッドを書き直したものです」とコンパイラーに伝える印です。

@Override を付けておくと、メソッド名を tostring と打ち間違えたときに、「型 Employee のメソッド tostring() はスーパータイプ・メソッドをオーバーライドまたは実装する必要があります」というエラーが出て、間違いに気づけます。付けなくても動きますが、必ず付ける習慣にしてください。

【便利な使い方】toString() を Eclipse に作ってもらう

メニューの ソース → toString() の生成 を選ぶと、フィールドを並べた toString() を自動で作れます。形が決まっているので、自分で書くより速くて確実です。この教材では、表示の形を決めたいので自分で書いています。

10.4 インターフェース

インターフェース は、「このメソッドを持つ」という約束だけを書いたものです。メソッドの名前・引数・戻り値の型だけを書き、中身({ } の処理)は書きません。中身は、そのインターフェースを 実装 するクラスが書きます。

  1. ch10 パッケージを右クリックし、新規 → インターフェース を選びます。「新規 Java インターフェース」の画面で、「名前」に Validatable と入力し、「完了」をクリックします。

    新規 Java インターフェースの画面。名前に Validatable
    図10-2 名前に Validatable と入力して「完了」

  2. 緑の行を入力します。

    ch10/Validatable.java
    package ch10;
    
    /** 値が正しいかを調べられることを表す */
    public interface Validatable {
    
        /** 登録や変更の前に、値が正しい範囲かを確かめる
         * @return 正しければ true */
        boolean isValid();
    
    }
    

    boolean isValid(); は、{ } が無く、; で終わっています。「boolean を返す isValid というメソッドを持つ」という約束だけです。

  3. Employee.java のクラスの行に implements Validatable を足し、isValid メソッドを書きます。

    ch10/Employee.java
    package ch10;
    
    /** 社員を表す */
    public class Employee implements Validatable {
    
        private String name;
        private int age;
    
        /** 登録や変更の前に、年齢が 15 以上 99 以下かを確かめる
         * @return 範囲内なら true */
        @Override
        public boolean isValid() {
            return age >= 15 && age <= 99;
        }
    
        public String getName() {
            return name;
        }
    

    implements Validatable と書いた時点で、isValid() を書くまでは「型 Employee は継承された抽象メソッド Validatable.isValid() を実装する必要があります」というエラーになります。約束したメソッドを必ず書かせる仕組みです。

  4. Main.java の main メソッドの最後に、緑の行を書き足します。

    ch10/Main.java(main メソッドの最後)
            System.out.println(e1);
            System.out.println(m1);
            Validatable v1 = e1;
            Validatable v2 = m1;
            System.out.println(e1.getName() + " の年齢は正しい:" + v1.isValid());
            System.out.println(m1.getName() + " の年齢は正しい:" + v2.isValid());
        }
    
  5. 保存して実行します。

    コンソール
    雷禅 海皇(26歳)
    院照 心愛(27歳)総務部の管理者
    雷禅 海皇 の年齢は正しい:true
    院照 心愛 の年齢は正しい:true
    
コード 意味
public interface Validatable { boolean isValid(); } インターフェースの定義。class の代わりに interface と書く。メソッドは中身を書かず ; で終える。メソッドは自動で public になる
class Employee implements Validatable Employee が Validatable を 実装 する。約束したメソッドを、public を付けて中身まで書く
Validatable v1 = e1; インターフェースの型の変数に、実装したクラスのオブジェクトを入れられる。v1 からは、Validatable で約束したメソッド(isValid())だけが呼べ、getName() などは呼べない

Manager は Employee を継承しているので、isValid() も引き継いでいます。Validatable v2 = m1; と書けるのはこのためです。

インターフェースを使う理由

インターフェースの型の変数(v1)を使う側は、「isValid() が呼べる」ことだけを知っていればよく、中身がどう書かれているか、どのクラスのオブジェクトかを気にしなくて済みます。Spring入門では、EmployeeRepository というインターフェースを自分で定義し、その中身(データベースを読み書きする処理)は Spring が用意します。使う側は、employeeRepository.findByEmpId(1) のように、約束されたメソッドを呼ぶだけです。

【知識メモ】インターフェースどうしの継承

インターフェースも、extends で別のインターフェースを継承できます。Spring入門の public interface EmployeeRepository extends JpaRepository<Employee, Integer> がそれで、JpaRepository が約束しているメソッド(保存・削除など)をすべて引き継いだうえで、自分のメソッドを足しています。クラスと違い、インターフェースは複数のインターフェースを継承することもできます。

10.5 Serializable

Java には、メソッドを1つも持たないインターフェースもあります。java.io.Serializable がその1つで、「このクラスのオブジェクトは、ファイルや通信用のデータに変換してよい」という印として使われます。

  1. Employee.java のクラスの行に、Serializable を足します。Seri と入力して Ctrl + Space を押し、候補から「Serializable - java.io」を選ぶと、import java.io.Serializable; も自動で入ります。

    ch10/Employee.java(前半)
    package ch10;
    
    import java.io.Serializable;
    
    /** 社員を表す */
    public class Employee implements Validatable, Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private String name;
        private int age;
    

    複数のインターフェースを実装するときは、, で区切って並べます。

  2. Manager.java にも、緑の行を書き足します。親クラスが Serializable なら、子クラスも Serializable になるので、同じ定数を書きます。

    ch10/Manager.java(前半)
    package ch10;
    
    /** 管理者を表す。社員の情報に加えて、管理する部署を持つ */
    public class Manager extends Employee {
    
        private static final long serialVersionUID = 1L;
    
        private String deptName;
    
  3. 保存して実行します。表示は変わりません。

    コンソール
    雷禅 海皇(26歳)
    院照 心愛(27歳)総務部の管理者
    雷禅 海皇 の年齢は正しい:true
    院照 心愛 の年齢は正しい:true
    

Serializable を付けると、Eclipse は「シリアライズ可能クラス Employee は long 型の static final serialVersionUID フィールドを宣言していません」という警告(黄色の印)を出します。serialVersionUID は、変換したデータがどの版のクラスのものかを表す番号で、private static final long serialVersionUID = 1L; と書いておくと警告が消えます。意味を深く考える必要はなく、「Serializable を付けたら、この1行も書く」と覚えておけば十分です。

【知識メモ】Spring入門での Serializable

Spring入門では、画面の入力内容を一時的に保存する仕組み(セッション)に Form クラスのオブジェクトを入れます。セッションに入れるクラスは Serializable を実装している必要があるので、Form クラスには implements Serializable と serialVersionUID の行を書きます。

10.6 うまくいかないときは

症状 考えられる原因と対処
「型 Employee は継承された抽象メソッド Validatable.isValid() を実装する必要があります」 implements Validatable と書いたのに、isValid() メソッドをまだ書いていないか、名前・引数・戻り値の型が違います。インターフェースの宣言と同じ形で書いてください。
「型 Employee のメソッド tostring() はスーパータイプ・メソッドをオーバーライドまたは実装する必要があります」 @Override を付けたメソッドの名前が、親のメソッドと違います。toString(S は大文字)に直してください。
「Validatable から継承されたメソッドの可視性を下げることはできません」 実装した isValid() に public が付いていません。インターフェースのメソッドを実装するときは、必ず public を付けます。
「型の不一致: Employee から Manager には変換できません」 Manager m = new Employee(); のように、親のオブジェクトを子の型の変数に入れています。逆は可能ですが、これはできません。
println(e1) で ch10.Employee@… と表示される toString() をオーバーライドしていないか、名前が違います。@Override を付けて確かめてください。
「Serializable を型に解決できません」 import java.io.Serializable; がありません。Serializable の末尾で Ctrl + Space を押して import を入れてください。

ほかのコンパイルエラーは、付録A「よくあるコンパイルエラー」 も参考にしてください。

10.7 まとめと確認問題

まとめ

  • 継承:class 子 extends 親 で、親のフィールドとメソッドを引き継ぐ。子のオブジェクトは親の型の変数に入れられる
  • すべてのクラスは Object を継承している。println(オブジェクト) は toString() の結果を表示する
  • オーバーライド:親のメソッドを子で書き直す。必ず @Override を付ける
  • インターフェース:interface で、メソッドの約束だけを書く。クラスは implements で実装し、約束したメソッドを public で書く。インターフェースの型の変数に、実装したクラスのオブジェクトを入れられる
  • Serializable はメソッドの無いインターフェース。実装したら private static final long serialVersionUID = 1L; も書く。子クラスにも書く

この章で使った書き方は、付録B「文法早見表」の「メソッドとクラス」 にまとめています。

確認問題

問1 class Manager extends Employee と書いたとき、Manager のオブジェクトで Employee の getName() は使えますか。

解答を見る

使えます。継承によって、親クラスのメソッドを引き継いでいるためです。

問2 @Override を付ける利点は何ですか。

解答を見る

メソッド名や引数を打ち間違えて、親のメソッドを書き直せていないときに、コンパイルエラーで気づけることです。

問3 インターフェースのメソッドと、クラスのメソッドの書き方の違いを答えてください。

解答を見る

インターフェースのメソッドは中身({ })を書かず、boolean isValid(); のように ; で終えます。中身は、実装するクラスが書きます。

問4 Employee implements Validatable と書いたのに isValid() を書かないと、どうなりますか。

解答を見る

「型 Employee は継承された抽象メソッド Validatable.isValid() を実装する必要があります」というコンパイルエラーになります。

問5 Serializable を実装したクラスに書く定数の行を答えてください。

解答を見る

private static final long serialVersionUID = 1L;


前へ

第9章 カプセル化とパッケージ

次へ

第11章 ラッパークラスとコレクション

目次へ

【Java入門】目次

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?