Javaクラス継承の完全解説!初心者でも理解できる10ステップ

初心者が学ぶJavaのクラスと継承の完全ガイドJava
この記事は約24分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Javaプログラミング言語の学習を始める際、クラスと継承は避けて通れない大切なテーマとなります。

この記事では、Javaの基本的な背景と、クラスと継承の概念を超絶詳細に解説していきます。

初心者の方でも安心して学べるよう、実用的なサンプルコードとその詳細な解説を交えながら進めていきます。

Javaの学習を始める方は必見です。

さらに、Javaの特徴とその歴史も紐解いていきますので、Java言語の全体像がよりクリアに理解できることでしょう。

●Javaとは

Javaは、1990年代初頭にサン・マイクロシステムズ(現在はオラクル社が所有)によって開発されたプログラム言語です。

初心者から上級者まで幅広く利用されるこの言語は、オブジェクト指向プログラミングの原則に従い設計されており、プラットフォーム非依存の特性があります。

これは、Javaで書かれたプログラムが異なる種類のコンピューターシステムで動作可能であることを意味します。

○Javaの特徴

Java言語の特徴を理解することは、プログラミングの学習において非常に重要なステップです。

Javaの主な特徴としては次の点が挙げられます。

□オブジェクト指向

Javaはオブジェクト指向プログラミング言語であり、データと手続きを一つの単位、すなわち「オブジェクト」として扱います。

これにより、コードの再利用性と拡張性が向上します。

□プラットフォーム非依存

一度Javaでプログラムを作成すると、異なるプラットフォームで実行できる特性があります。

これはJava仮想マシン(JVM)と呼ばれる中間言語を介して行われます。

□セキュリティ

Javaは、セキュリティを非常に重視して設計されており、多くのセキュリティ機能が組み込まれています。

□万能

ウェブアプリケーションからモバイルアプリケーションまで、多岐にわたるアプリケーションの開発が可能です。

ここで、サンプルコードを用いて、Javaの基本的なコーディングスタイルを見てみましょう。

下記のサンプルコードは、「Hello, World!」というメッセージを出力する簡単なJavaプログラムです。

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

このコードは非常に簡単なものですが、Javaプログラムの基本的な構造を表しています。

public class HelloWorld は、HelloWorldというクラスを定義しています。

public static void main(String[] args) は、プログラムのエントリーポイントであるmainメソッドを定義しています。

そして、System.out.println("Hello, World!"); は、コンソールに「Hello, World!」というメッセージを出力します。

このコードを実行すると、コンソールには「Hello, World!」と表示される結果となります。

○Javaの歴史

Java言語の歴史は1991年に始まります。

この年、サン・マイクロシステムズのエンジニアたちが、消費者向け電子機器のための新しいプログラム言語の開発を始めました。

Javaは当初、「Oak」という名前で知られ、後に商標の問題から「Java」と改名されました。

1995年に公式にリリースされ、その後ウェブアプリケーションの開発におけるデファクトスタンダードとなりました。Javaはその後も進化を続け、多くのバージョンアップを重ねてきました。

現在でも、多くのシステムで利用されている堅実かつ柔軟性の高い言語として知られています。

●Javaのクラスとは

Javaのクラスは、オブジェクト指向プログラミングの基本的な構成単位として機能します。

クラスは、特定の種類のオブジェクトが持つべき属性(変数)と動作(メソッド)を定義する青写真のようなものです。

それぞれのクラスは新しいデータ型を定義し、それに基づいてオブジェクトを作成することができます。

これにより、コードの再利用と整理が簡単になり、大規模なプロジェクトでも管理が容易となります。

○クラスの定義

Javaでクラスを定義する際には、「class」というキーワードを使用します。クラス名は大文字から始めるのが慣習です。

クラス内部には、そのクラスが持つべき属性とメソッドを定義します。

簡単な「Car」クラスを定義するサンプルコードを紹介します。

public class Car {
    // 属性: 車のブランド名
    String brand;

    // メソッド: 車を走らせる
    public void drive() {
        System.out.println(brand + "が走ります。");
    }
}

このコードでは、Carクラスを公開範囲で定義しており、「brand」という属性と、「drive」というメソッドを持っています。

driveメソッドは車が走る動作をコンソールに表示する簡単なものです。

○クラスの属性とメソッド

クラスの属性とは、クラスが持つべきデータの変数のことで、クラスのメソッドはそのデータに対する操作を表現します。

□属性の定義方法

属性はクラス内部に変数として定義されます。

属性の定義は、データ型と変数名を指定することで行います。

データ型には、プリミティブ型(int, double, charなど)やクラス型(String, Arrayなど)があります。

下記のサンプルコードでは、Carクラスにいくつかの属性を追加しています。

public class Car {
    // 属性の定義
    String brand;
    int year;
    double price;

    // メソッドの定義は後述
}

このコードでは、「brand」というString型の属性、「year」というint型の属性、「price」というdouble型の属性をCarクラスに追加しています。

□メソッドの定義方法

メソッドの定義は、戻り値の型、メソッド名、括弧内にパラメータリスト(必要に応じて)、そしてメソッド本体を含めることで行います。

Carクラスに「setDetails」というメソッドを追加したサンプルコードを紹介します。

public class Car {
    // 属性の定義(前述のコードを参照)

    // メソッドの定義
    public void setDetails(String brand, int year, double price) {
        this.brand = brand;
        this.year = year;
        this.price = price;
    }

    public void drive() {
        System.out.println(brand + "が走ります。");
    }
}

このコードでは、「setDetails」というメソッドを追加しており、このメソッドは3つのパラメータを受け取り、それらをCarクラスの属性に設定します。

また、driveメソッドも引き続き含まれています。

このコードを実行すると、「setDetails」メソッドを使ってCarオブジェクトの属性を設定し、その後「drive」メソッドを呼び出すことで車が走る動作をコンソールに表示することができます。

○クラスのインスタンス化

Javaプログラミングの基本的なステップとして、「クラスのインスタンス化」が非常に重要なステップとなります。

クラスのインスタンス化とは、クラスからオブジェクトを生成するプロセスのことを指します。

ここでは、Java言語でクラスをインスタンス化する手法とその実行結果について、初心者の方でも理解できるように丁寧に解説してまいります。

まず初めに、クラスを定義します。

クラスは、Javaのプログラムの基本的な構成要素となり、オブジェクト指向プログラムを構築するためのテンプレートのような存在です。

次のような形でクラスを定義できます。

public class 車 {
    String モデル名;
    int 速度;

    public void 加速する(int 増速量) {
        速度 += 増速量;
    }
}

こちらのコードは「車」という名前のクラスを定義しており、そのクラスには「モデル名」と「速度」という属性と、「加速する」というメソッドがあります。

属性はオブジェクトの状態を表し、メソッドはオブジェクトが行えるアクションを表します。

次に、このクラスから実際のオブジェクトを生成します。

それを「インスタンス化」と言います。以下のようなコードを使ってインスタンス化を行います。

車 マイカー = new 車();

この行は、クラスの新しいインスタンスを作成し、それをマイカーという変数に代入しています。

この時点で、マイカーオブジェクトはクラスの属性とメソッドを持っています。

そして、オブジェクトの属性をセットし、メソッドを使用することができます。

次のようなコードでそれを行います。

マイカー.モデル名 = "トヨタ";
マイカー.速度 = 0;
マイカー.加速する(50);

この段階で、マイカーオブジェクトのモデル名は「トヨタ」にセットされ、速度は0にセットされます。

そして、「加速する」メソッドを呼び出し、その速度を50増加させます。

このため、マイカーオブジェクトの速度属性は50となります。

●Javaの継承とは

Javaの継承は、あるクラスが別のクラスの属性やメソッドを引き継ぐことを指します。

これにより、既存のコードの再利用や新しいクラスの作成を簡単にすることができます。

Javaでは、継承の概念は非常に重要な役割を果たしており、オブジェクト指向の核心的な特徴の1つと言えるでしょう。

○継承の基本概念

継承を理解するための簡単な例を考えてみましょう。

自動車を表す「Car」というクラスがあるとします。

この「Car」クラスには「色」や「速度」などの属性や「走る」や「止まる」といったメソッドがあるとしましょう。

そして、この「Car」クラスをベースに、トラックを表す「Truck」クラスを作成したい場合、継承を利用すると「Truck」クラスには「Car」の全ての属性やメソッドが引き継がれます。

このように、共通の性質や機能を持つクラスをベースにして、新しいクラスを効率的に作成することができるのです。

○継承の利点と使い方

□継承を利用したコードの再利用

継承の最も大きな利点は、コードの再利用性を向上させることです。

例えば、あるクラスに定義されたメソッドや属性を別のクラスでも使用したい場合、そのクラスを継承するだけで同じ機能や属性を持つ新しいクラスを作成することができます。

これにより、同じコードを何度も書く必要がなくなり、プログラムのメンテナンスもしやすくなります。

// 基本となるCarクラス
class Car {
    String color;
    int speed;

    void run() {
        // 走行する処理
    }

    void stop() {
        // 停止する処理
    }
}

// Carクラスを継承したTruckクラス
class Truck extends Car {
    int payload;

    void loadGoods() {
        // 荷物を積む処理
    }
}

この例では、「Truck」クラスは「Car」クラスの属性やメソッドを引き継いでいます。

そのため、「Truck」クラスのインスタンスは「run」や「stop」といったメソッドを使用することができます。

□ポリモーフィズムの実現

継承は、ポリモーフィズムというオブジェクト指向の重要な概念を実現する上でも必要不可欠です。

ポリモーフィズムとは、異なるクラスのオブジェクトを同一のインターフェースで操作することができる特性を指します。

継承を使用すると、親クラスの型の変数で子クラスのオブジェクトを扱うことができます。

Car myCar = new Truck();

この例では、「Car」クラスの変数「myCar」で、「Truck」クラスのインスタンスを参照しています。

これにより、異なるクラスのオブジェクトも同一のインターフェースで扱うことができるようになります。

○継承の注意点と対処法

Javaのクラスの継承は、クラス間で属性やメソッドを共有する非常に強力な機能ですが、その強力さゆえに注意しなければならない点や、適切な使用法があります。

それでは、継承の際に陥りがちなトラップや、それに対処する方法について詳細に説明します。

まず、適切な継承の使用法について理解することが重要です。

継承を利用する時、最も基本的な注意点は、親クラスと子クラス間での関係が「is-a」関係であることを確認することです。

例えば、「車」クラスから「トラック」クラスを派生させる際には、トラックは車である、という「is-a」関係が成立します。

次にコードのサンプルを挙げます。

このコードでは「動物」クラスから「犬」クラスを派生させます。

そして、「犬」クラス内に独自のメソッドを追加します。

class 動物 {
    void 鳴く() {
        System.out.println("動物が鳴いています");
    }
}

class 犬 extends 動物 {
    void 鳴く() {
        System.out.println("犬がワンワンと鳴いています");
    }
    void しっぽを振る() {
        System.out.println("犬がしっぽを振っています");
    }
}

このコードを実行すると、「犬」クラスのインスタンスである犬が「ワンワン」と鳴き、「しっぽを振る」行動を取ります。

しかし、親クラスの「動物」クラスの「鳴く」メソッドも利用可能です。

次に注意点として挙げられるのは、親クラスのプライベート属性やメソッドは、子クラスからアクセスすることができない点です。

これに対処するためには、親クラスの属性やメソッドに適切なアクセス修飾子を設定することが求められます。

また、継承関係を複雑にしすぎると、コードの管理が困難になります。

継承の階層はなるべくシンプルに保ち、必要に応じてコンポジションを利用することが推奨されます。

そして、継承を使った時にしばしば起きる問題が、メソッドのオーバーライドです。

親クラスのメソッドを子クラスでオーバーライドする際には、@Overrideアノテーションを使用してコンパイラにその意図を明示的に表すことが重要です。

ここまでの解説を踏まえた上で、具体的な対処法を紹介します。

継承の注意点に対処するための一般的な手法は次の通りです。

  1. 継承関係を明確に定義し、「is-a」関係を保つ
  2. 親クラスの属性やメソッドに適切なアクセス修飾子を設定する
  3. 継承の階層をシンプルに保つ
  4. 必要に応じてコンポジションを利用する
  5. オーバーライドする際には@Overrideアノテーションを利用する

以上の方法を利用することで、継承を効果的かつ安全に利用することができます。

●実際のコーディング

コーディングを行う際には、まず基本的なクラスの構造を理解することが第一歩となります。

Javaにおけるクラスは、オブジェクト指向プログラムの基本的な構成単位として機能し、データとそれを操作するメソッドを一緒にまとめる役割を果たします。

○クラスの作り方

クラスの作成は、Javaのプログラムの基本とも言える部分です。

ここでは、基本的なクラスの作成方法と、クラス内でのコンストラクタの利用方法について詳しく説明します。

□基本的なクラスの作成

基本的なクラスの作成にはいくつかのステップがあります。

まずは、クラスの宣言から始めます。

クラス宣言は「class」キーワードを用いて行います。

次に、クラス内に属性とメソッドを定義します。

下記のサンプルコードは、簡単な「Person」クラスを作成する例を表しています。

public class Person {
    // 属性の定義
    String name;
    int age;

    // メソッドの定義
    public void introduce() {
        System.out.println("私の名前は" + name + "で、年齢は" + age + "歳です。");
    }
}

このコードによって作成される「Person」クラスには、「name」や「age」といった属性と、「introduce」というメソッドが含まれます。

メソッド「introduce」は、その人物の名前と年齢を出力する機能を持っています。

□コンストラクタの利用

コンストラクタはクラスがインスタンス化される際に自動的に呼び出される特殊なメソッドです。

コンストラクタはクラス名と同名である必要があり、戻り値の型を指定することはありません。

下記のサンプルコードは、「Person」クラスにコンストラクタを追加したものです。

public class Person {
    // 属性の定義
    String name;
    int age;

    // コンストラクタの定義
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // メソッドの定義
    public void introduce() {
        System.out.println("私の名前は" + name + "で、年齢は" + age + "歳です。");
    }
}

このコンストラクタは、新しい「Person」オブジェクトを作成する際に、「name」と「age」の属性を初期化します。

このようにコンストラクタを利用することで、オブジェクトの作成と同時に属性の初期設定を行うことが可能となります。

○継承を利用したクラスの作成

Javaの継承は、既存のクラスを基に新しいクラスを作成する際に役立つ概念です。

この概念を理解することで、コードの再利用性が向上し、より簡潔かつ整理されたコードを作成することが可能となります。

ここでは、継承を利用したクラスの作成方法について深く掘り下げていきます。

見ていきましょう。

□基本的な継承の実装

Javaで継承を実装する基本的な方法は、既存のクラスを拡張して新しいクラスを作成することです。

これは「extends」キーワードを使用して行われます。

まず、基本的な親クラスを作成しましょう。

public class 親クラス {
    // 属性
    public String 属性1 = "親クラスの属性1";

    // メソッド
    public void メソッド1() {
        System.out.println("親クラスのメソッド1が呼び出されました");
    }
}

上記のコードは親クラスとして機能するシンプルなクラスを表しています。

このクラスには一つの属性と一つのメソッドが含まれています。

次に、このクラスを継承して子クラスを作成します。

public class 子クラス extends 親クラス {
    // 子クラスの新しい属性
    public String 属性2 = "子クラスの属性2";

    // 子クラスの新しいメソッド
    public void メソッド2() {
        System.out.println("子クラスのメソッド2が呼び出されました");
    }
}

このコードでは、「extends」キーワードを使用して親クラスを継承しています。

子クラスには新しい属性と新しいメソッドが追加されています。また、親クラスの属性とメソッドも利用できます。

□オーバーライドとオーバーロード

継承の利用時に非常に重要となるのが「オーバーライド」と「オーバーロード」という二つの概念です。

オーバーライドは、子クラスで親クラスのメソッドを新しい実装で上書きする技術です。

一方、オーバーロードは、同じ名前のメソッドを異なる引数で複数定義する技術です。

それぞれ見ていきましょう。

まず、オーバーライドの実例です。

public class 子クラス extends 親クラス {

    // オーバーライド
    @Override
    public void メソッド1() {
        System.out.println("子クラスでメソッド1がオーバーライドされました");
    }

    // 子クラスの新しいメソッド
    public void メソッド2() {
        System.out.println("子クラスのメソッド2が呼び出されました");
    }
}

このコードでは、「@Override」アノテーションを使用してメソッド1をオーバーライドしています。

次に、オーバーロードの実例を見ていきます。

public class 親クラス {

    // オーバーロード
    public void メソッド3(String 引数1) {
        System.out.println("引数1: " + 引数1);
    }

    public void メソッド3(String 引数1, String 引数2) {
        System.out.println("引数1: " + 引数1 + ", 引数2: " + 引数2);
    }
}

このコードでは、「メソッド3」をオーバーロードしており、引数の数が異なるため、メソッド3は二つの異なる形で呼び出せます。

○実用的なサンプルコード

Java言語を理解する上で、実用的なサンプルコードは非常に重要です。

ここでは、Javaのクラスと継承のコンセプトを用いた実際のプログラムの実例を詳細に解説いたします。

ここでは、Javaのクラス継承を活用したプログラムの作成方法を、初心者でも理解できるよう心掛けて説明いたします。

□継承を利用したプログラムの実例

継承は、オブジェクト指向プログラミングの基本的な特性の一つであり、コードの再利用を助け、プログラムの構造を整理し、可読性を向上させます。

ここでは、継承の基本的な概念を活用したJavaプログラムのサンプルコードとその詳細な説明を提供します。

最初に、基本的な親クラスを作成します。

この親クラスは「Vehicle」と名付けられ、いくつかの基本的な属性とメソッドを持っています。

public class Vehicle {
    String name;
    int speed;

    public Vehicle(String name, int speed) {
        this.name = name;
        this.speed = speed;
    }

    public void showInfo() {
        System.out.println("車両名: " + name + "、速度: " + speed + "km/h");
    }
}

上記のサンプルコードは、車両の基本的な情報を管理するためのクラスを表しています。

このクラスには、車両の名前と速度を保持する属性と、その情報を表示するメソッドが含まれます。

次に、この「Vehicle」クラスを継承して新しい子クラス「Car」を作成します。

この新しいクラスには、親クラスの属性とメソッドに加えて新しい属性とメソッドも含まれます。

public class Car extends Vehicle {
    int fuel;

    public Car(String name, int speed, int fuel) {
        super(name, speed);
        this.fuel = fuel;
    }

    public void showCarDetails() {
        System.out.println("車両名: " + name + "、速度: " + speed + "km/h、燃料量: " + fuel + "L");
    }
}

上記のサンプルコードでは、新しいクラス「Car」が「Vehicle」クラスを継承しています。

そして、新しい属性「fuel」と新しいメソッド「showCarDetails」が追加されました。

このメソッドは、車両の名前、速度、そして燃料量を表示します。

それでは、このプログラムがどのように動作するかを表すために、メインメソッドを作成します。

public class Main {
    public static void main(String[] args) {
        Car myCar = new Car("プリウス", 100, 50);
        myCar.showInfo();
        myCar.showCarDetails();
    }
}

このメインメソッドでは、新しい「Car」オブジェクトを作成し、そのオブジェクトのshowInfoメソッドとshowCarDetailsメソッドを呼び出します。

実行結果は、車両の詳細情報が表示されることとなります。

●応用例とサンプルコード

Javaのクラスと継承の特性を理解した上で、次に進むステップは応用例と実際のサンプルコードを学習することです。

ここでは、Javaでクラスをカスタマイズする方法や継承をさらに活用するテクニックに焦点を当てて解説していきます。

○クラスのカスタマイズ

Java言語におけるクラスのカスタマイズは、プログラムの拡張性と再利用性を高める重要なステップです。

ここでは、既存のクラスをカスタマイズする方法について詳しく説明していきます。

まずは基本的なクラスのカスタマイズ方法から学んでいきましょう。

例えば、あるクラスに新しいメソッドを追加したい場合があります。

このようなカスタマイズは、クラスに新たな機能を付与し、そのクラスをさらに強力で柔軟なものに変えることができます。

次に、具体的なサンプルコードを見てみましょう。

public class CustomizedClass extends ExistingClass {
    // 新たなメソッドを追加
    public void newMethod() {
        System.out.println("新たなメソッドが実行されました");
    }
}

このコードでは、ExistingClassという既存のクラスを継承して新しいクラスCustomizedClassを作成しています。

そして、newMethodという新しいメソッドを追加しています。

このメソッドは単に「新たなメソッドが実行されました」と表示するだけの簡単なものですが、これによってCustomizedClassExistingClassよりも多くの機能を持つことになります。

○継承のさらなる活用

Javaの継承をさらに活用する方法について学んでいきましょう。

継承の概念はオブジェクト指向プログラミングの核心であり、さまざまな応用が可能です。

□抽象クラスとインターフェースの利用

抽象クラスとインターフェースは、Javaプログラミングにおける高度な継承の利用法の一つです。

下記のサンプルコードは、抽象クラスとインターフェースの基本的な利用方法を表しています。

abstract class AbstractClass {
    abstract void abstractMethod();
}

interface InterfaceExample {
    void interfaceMethod();
}

class ImplementationClass extends AbstractClass implements InterfaceExample {
    @Override
    void abstractMethod() {
        System.out.println("抽象メソッドが実装されました");
    }

    @Override
    public void interfaceMethod() {
        System.out.println("インターフェースメソッドが実装されました");
    }
}

このサンプルコードでは、AbstractClassという抽象クラスとInterfaceExampleというインターフェースを定義しています。

そして、ImplementationClassというクラスではこれらを継承してメソッドを実装しています。

抽象クラスとインターフェースを利用することで、更に洗練されたコード構造を作成することができます。

□デザインパターンの一例

デザインパターンは、特定の問題を解決するための標準的なソリューションを提供します。

デザインパターンの一例としてシングルトンパターンのサンプルコードを紹介します。

public class Singleton {
    private static Singleton instance;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

このコードではSingletonパターンを実装しています。

このパターンは、クラスのインスタンスが一つしか存在しないことを保証するものです。

getInstanceメソッドを使ってインスタンスを取得するとき、既にインスタンスが存在していればそれを返し、存在していなければ新たにインスタンスを作成します。

まとめ

Javaのクラスと継承の概念は、プログラムの効率と柔軟性を高めるための基本的な要素です。

この記事では、Javaの基本概念からクラスの作成方法、そして継承の利用法までを初心者でも理解できる形で解説しました。

具体的なコーディング例を通じて、Javaプログラミングの基礎を固める手助けをしたことを願っています。

実際のコーディング時には、今回学んだ知識を基に、さらに応用的なプログラムを作成してみてください。

例えば、継承を利用したクラスの作成やオーバーライドとオーバーロードの技法を用いたり、更にはデザインパターンの一例を学ぶなど、可能性は広がります。

また、抽象クラスやインターフェースの利用方法も、今後の学習の範囲に含めると良いでしょう。

また、学習を進める中で疑問点や難しいコンセプトに遭遇した場合は、遠慮なく質問し、学びを深めることが重要です。

この記事が、あなたのJavaプログラミング学習の旅の第一歩となることを期待しています。