Javaの基礎Java

Javaの基礎:多態性(ポリモーフィズム)を解説

Java多態性解説ページのアイキャッチ画像 Javaの基礎

この記事では、オブジェクト指向プログラミングにおける多態性の概念と、Javaを使った具体的な実装例を解説します。動物の鳴き声と図形の面積計算という2つの実践的なプログラム例を通じて、その適用方法を学びます。

はじめに

この記事のコードをコピペしてEclipseで出力結果を確認してみよう

多態性の基本

多態性(ポリモーフィズム)は、オブジェクト指向プログラミングの重要な概念の1つです。多態性とは、同じインターフェースを持つ異なるクラスのオブジェクトが、同じメソッド呼び出しに対して異なる動作をすることを指します。

多態性の主な利点は以下の通りです:

  1. コードの再利用性の向上
  2. プログラムの柔軟性と拡張性の増加
  3. メンテナンス性の向上

プログラム例1: 動物の鳴き声

以下は、動物の鳴き声を表現する簡単な例です。

Animal.java

Java
// 動物の基本クラス
abstract class Animal {
    // 抽象メソッド:サブクラスで実装する必要がある
    public abstract void makeSound();
}

Dog.java

Java
// 犬クラス
class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("ワンワン!");
    }
}

Cat.java

Java
// 猫クラス
class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("ニャーニャー!");
    }
}

AnimalSounds.java

Java
// メインクラス
public class AnimalSounds {
    public static void main(String[] args) {
        // 動物の配列を作成
        Animal[] animals = new Animal[2];
        animals[0] = new Dog();
        animals[1] = new Cat();

        // 各動物の鳴き声を出力
        for (Animal animal : animals) {
            animal.makeSound();
        }
    }
}

出力結果:

ワンワン!
ニャーニャー!

このプログラムでは、Animalクラスを基底クラスとし、DogCatクラスがそれを継承しています。各サブクラスはmakeSound()メソッドをオーバーライドして、独自の鳴き声を実装しています

メインメソッドでは、Animal型の配列にDogCatのインスタンスを格納しています。forループで各動物のmakeSound()メソッドを呼び出すと、それぞれの動物に応じた鳴き声が出力されます。これが多態性の典型的な例です。

Animal.javaの解説

クラス定義

Java
abstract class Animal {
    // ...
}
  • abstract キーワードは、このクラスが抽象クラスであることを示します。
  • 抽象クラスは、直接インスタンス化できないクラスです。
  • Animalは動物の基本的な特性や行動を定義するための基底クラスです。

抽象メソッド

Java
public abstract void makeSound();
  • abstract キーワードは、このメソッドが抽象メソッドであることを示します。
  • 抽象メソッドは、メソッドの本体(実装)を持たないメソッドです。
  • publicは、このメソッドが他のクラスからアクセス可能であることを示します。
  • voidは、このメソッドが値を返さないことを示します。
  • makeSound()は、動物が音を出す行動を表現するメソッドです。

重要なポイント:

  1. 抽象クラスは、共通の特性や振る舞いを定義するために使用されます。
  2. 抽象クラスを継承するサブクラスは、すべての抽象メソッドを実装する必要があります
  3. この設計により、異なる動物の種類に対して共通のインターフェースを提供しつつ、各動物固有の実装を可能にします。

このコードは、オブジェクト指向プログラミングの重要な概念である抽象化継承を示す良い例です。

Dog.javaの解説

クラス定義

Java
class Dog extends Animal {
    // ...
}
  • DogクラスはAnimalクラスを継承しています。
  • extends キーワードは、DogクラスがAnimalクラスのサブクラスであることを示します。
  • これにより、DogクラスはAnimalクラスの特性を引き継ぎ、拡張することができます。

メソッドのオーバーライド

Java
@Override
public void makeSound() {
    System.out.println("ワンワン!");
}
  • @Override アノテーションは、このメソッドが親クラスのメソッドをオーバーライド(上書き)していることを明示します。
  • makeSound()メソッドは、Animalクラスで定義された抽象メソッド具体的に実装しています。
  • System.out.println()は、コンソールに文字列を出力するJavaの標準的な方法です。

重要なポイント:

  1. DogクラスはAnimalクラスの具体的な実装です。
  2. 抽象メソッドmakeSound()オーバーライドすることで、犬特有の鳴き声を実装しています。
  3. この実装により、Dogオブジェクトは"ワンワン!"と出力することで、犬の鳴き声を表現します。
  4. 継承メソッドのオーバーライドは、オブジェクト指向プログラミングの重要な概念です。

このコードは、抽象クラス具体化する方法と、多態性(ポリモーフィズム)の基本を示しています。Animal型の変数でDogオブジェクトを参照しても、makeSound()を呼び出すと犬の鳴き声が出力されます。

Cat.javaの解説

クラス定義

Java
class Cat extends Animal {
    // ...
}
  • CatクラスはAnimalクラスを継承しています。
  • extends キーワードは、CatクラスがAnimalクラスのサブクラスであることを示します。
  • これにより、CatクラスはAnimalクラスの特性を引き継ぎ、拡張することができます。

メソッドのオーバーライド

Java
@Override
public void makeSound() {
    System.out.println("ニャーニャー!");
}
  • @Override アノテーションは、このメソッドが親クラスのメソッドをオーバーライド(上書き)していることを明示します。
  • makeSound()メソッドは、Animalクラスで定義された抽象メソッド具体的に実装しています。
  • System.out.println()は、コンソールに文字列を出力するJavaの標準的な方法です。

重要なポイント:

  1. CatクラスはAnimalクラスのもう一つの具体的な実装です。
  2. 抽象メソッドmakeSound()オーバーライドすることで、猫特有の鳴き声を実装しています。
  3. この実装により、Catオブジェクトは"ニャーニャー!"と出力することで、猫の鳴き声を表現します。
  4. DogクラスとCatクラスは、同じAnimalクラスを継承していますが、異なる鳴き声を実装しています。これは多態性の一例です。

このコードは、同じインターフェース(ここではmakeSound()メソッド)を持ちながら、異なる実装を提供する方法を示しています。これにより、プログラムの柔軟性拡張性が向上します。例えば、新しい動物クラス(例:Bird)を追加する際も、同じパターンで簡単に実装できます。

AnimalSounds.javaの解説

クラス定義

Java
public class AnimalSounds {
    // ...
}
  • AnimalSoundsメインクラスです。
  • publicキーワードは、このクラスが他のパッケージからもアクセス可能であることを示します。

メインメソッド

Java
public static void main(String[] args) {
    // ...
}
  • mainメソッドはプログラムのエントリーポイントです。
  • staticキーワードは、このメソッドがクラスレベルで呼び出せることを示します。

動物の配列作成

Java
Animal[] animals = new Animal[2];
animals[0] = new Dog();
animals[1] = new Cat();
  • Animal型の配列を作成し、異なる動物オブジェクトを格納しています。
  • 多態性により、Animal型の配列にDogCatのオブジェクトを格納できます。

鳴き声の出力

Java
for (Animal animal : animals) {
    animal.makeSound();
}
  • 拡張for文(foreach文)を使用して、配列内の各動物に対して処理を行います。
  • animal.makeSound()は、各動物のmakeSound()メソッドを呼び出します。
  • 多態性により、実行時に各オブジェクトの適切なmakeSound()メソッドが呼び出されます。

重要なポイント:

  1. このクラスは抽象クラスと継承の利点を示しています。
  2. 多態性により、異なる動物クラスを同じ型(Animal)で扱えます。
  3. ループ内での動的メソッド呼び出しは、オブジェクト指向プログラミングの強力な機能を示しています。
  4. このコードは拡張性が高く、新しい動物クラスを追加しても、メインクラスの変更は最小限で済みます。

このコードは、抽象クラス継承多態性動的ディスパッチといったオブジェクト指向プログラミングの主要な概念を実践的に示しています。これにより、柔軟で保守性の高いコードが実現されています。

動的ディスパッチとは、実行時(ランタイム)にオーバーライドされたメソッドの呼び出しを解決するプロセスです。簡単に言えば、どのメソッドを実行するかを実行時に決定する仕組みです。

プログラム例2: 図形の面積計算

次に、異なる図形の面積を計算する例を見てみましょう。

Shape.java

Java
// 図形の基本クラス
abstract class Shape {
    // 抽象メソッド:面積を計算する
    public abstract double calculateArea();
}

Circle.java

Java
// 円クラス
class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

Rectangle.java

Java
// 長方形クラス
class Rectangle extends Shape {
    private double width;
    private double height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public double calculateArea() {
        return width * height;
    }
}

ShapeAreas.java

Java
// メインクラス
public class ShapeAreas {
    public static void main(String[] args) {
        // 図形の配列を作成
        Shape[] shapes = new Shape[2];
        shapes[0] = new Circle(5);
        shapes[1] = new Rectangle(4, 6);

        // 各図形の面積を計算して出力
        for (Shape shape : shapes) {
            System.out.println("面積: " + shape.calculateArea());
        }
    }
}

出力結果:

面積: 78.53981633974483
面積: 24.0

この例では、Shapeクラスを基底クラスとし、CircleRectangleクラスがそれを継承しています。各サブクラスはcalculateArea()メソッドをオーバーライドして、それぞれの図形に応じた面積計算を実装しています

メインメソッドでは、Shape型の配列にCircleRectangleのインスタンスを格納しています。forループで各図形のcalculateArea()メソッドを呼び出すと、それぞれの図形に応じた面積が計算されます。これも多態性の良い例です。

Shape.javaの解説

クラス定義

Java
abstract class Shape {
    // ...
}
  • abstract キーワードは、このクラスが抽象クラスであることを示します。
  • Shape図形の基本クラスとして定義されています。
  • 抽象クラスは直接インスタンス化できないクラスです。

抽象メソッド

Java
public abstract double calculateArea();
  • abstract キーワードは、このメソッドが抽象メソッドであることを示します。
  • 抽象メソッドはメソッドの本体(実装)を持たないメソッドです。
  • publicは、このメソッドが他のクラスからアクセス可能であることを示します。
  • doubleは、このメソッドが倍精度浮動小数点数を返すことを示します。
  • calculateArea()は、図形の面積を計算するためのメソッドです。

重要なポイント:

  1. この抽象クラスは、すべての図形に共通する特性(面積の計算)を定義しています。
  2. サブクラス(具体的な図形クラス)は、この抽象メソッドを必ず実装する必要があります。
  3. この設計により、異なる図形に対して共通のインターフェースを提供しつつ、各図形固有の面積計算方法を実装できます。

このコードは、オブジェクト指向プログラミングの重要な概念である抽象化を示しています。これにより、プログラムの柔軟性拡張性が向上し、新しい図形クラスを追加する際の基盤となります。

Circle.javaの解説

クラス定義

Java
class Circle extends Shape {
    // ...
}
  • CircleクラスはShapeクラスを継承しています。
  • extends キーワードは、CircleクラスがShapeクラスのサブクラスであることを示します。

インスタンス変数

Java
private double radius;
  • radiusは円の半径を表すプライベート変数です。
  • privateキーワードにより、この変数はこのクラス内でのみアクセス可能です。

コンストラクタ

Java
public Circle(double radius) {
    this.radius = radius;
}
  • このコンストラクタは、円の半径を引数として受け取り、インスタンス変数を初期化します。
  • this キーワードは、現在のオブジェクトを参照します。

メソッドのオーバーライド

Java
@Override
public double calculateArea() {
    return Math.PI * radius * radius;
}
  • @Override アノテーションは、このメソッドが親クラスのメソッドをオーバーライドしていることを明示します。
  • calculateArea()メソッドは、Shapeクラスの抽象メソッドを具体的に実装しています。
  • 円の面積計算式(πr²)を使用して面積を計算しています。
  • Math.PIは、JavaのMathクラスで定義されている円周率(π)の値です。

重要なポイント:

  1. CircleクラスはShape抽象クラスの具体的な実装です。
  2. カプセル化の原則に従い、radius変数をprivateにしています。
  3. コンストラクタを通じて、オブジェクト生成時に半径を設定できます。
  4. calculateArea()メソッドの実装により、円の面積を正確に計算できます。

このコードは、抽象クラスの具体化継承カプセル化メソッドのオーバーライドといったオブジェクト指向プログラミングの重要な概念を実践的に示しています。これにより、Shapeクラスの抽象的な概念を、円という具体的な図形に適用しています。

Rectangle.javaの解説

クラス定義

Java
class Rectangle extends Shape {
    // ...
}
  • RectangleクラスはShapeクラスを継承しています。
  • extends キーワードは、RectangleクラスがShapeクラスのサブクラスであることを示します。

インスタンス変数

Java
private double width;
private double height;
  • widthheightは長方形の幅と高さを表すプライベート変数です。
  • privateキーワードにより、これらの変数はこのクラス内でのみアクセス可能です。

コンストラクタ

Java
public Rectangle(double width, double height) {
    this.width = width;
    this.height = height;
}
  • このコンストラクタは、長方形の幅と高さを引数として受け取り、インスタンス変数を初期化します。
  • this キーワードは、現在のオブジェクトを参照します。

メソッドのオーバーライド

Java
@Override
public double calculateArea() {
    return width * height;
}
  • @Override アノテーションは、このメソッドが親クラスのメソッドをオーバーライドしていることを明示します。
  • calculateArea()メソッドは、Shapeクラスの抽象メソッドを具体的に実装しています。
  • 長方形の面積計算式(幅 × 高さ)を使用して面積を計算しています。

重要なポイント:

  1. RectangleクラスはShape抽象クラスのもう一つの具体的な実装です。
  2. カプセル化の原則に従い、widthheight変数をprivateにしています。
  3. コンストラクタを通じて、オブジェクト生成時に幅と高さを設定できます。
  4. calculateArea()メソッドの実装により、長方形の面積を簡単に計算できます。

このコードは、Circleクラスと同様に、抽象クラスの具体化継承カプセル化メソッドのオーバーライドの概念を示しています。Shapeクラスの抽象的な概念を、長方形という別の具体的な図形に適用することで、多態性の利点を実証しています。これにより、異なる図形クラスを同じインターフェース(calculateArea()メソッド)で扱うことができます。

ShapeAreas.javaの解説

クラス定義

Java
public class ShapeAreas {
    // ...
}
  • ShapeAreasメインクラスです。
  • publicキーワードは、このクラスが他のパッケージからもアクセス可能であることを示します。

メインメソッド

Java
public static void main(String[] args) {
    // ...
}
  • mainメソッドはプログラムのエントリーポイントです。
  • staticキーワードは、このメソッドがクラスレベルで呼び出せることを示します。

図形の配列作成

Java
Shape[] shapes = new Shape[2];
shapes[0] = new Circle(5);
shapes[1] = new Rectangle(4, 6);
  • Shape型の配列を作成し、異なる図形オブジェクトを格納しています。
  • 多態性により、Shape型の配列にCircleRectangleのオブジェクトを格納できます。

面積の計算と出力

Java
for (Shape shape : shapes) {
    System.out.println("面積: " + shape.calculateArea());
}
  • 拡張for文(foreach文)を使用して、配列内の各図形に対して処理を行います。
  • shape.calculateArea()は、各図形のcalculateArea()メソッドを呼び出します。
  • 多態性により、実行時に各オブジェクトの適切なcalculateArea()メソッドが呼び出されます。

重要なポイント:

  1. このクラスは抽象クラスと継承の利点を実践的に示しています。
  2. 多態性により、異なる図形クラスを同じ型(Shape)で扱えます。
  3. ループ内での動的メソッド呼び出しは、オブジェクト指向プログラミングの強力な機能を示しています。
  4. このコードは拡張性が高く、新しい図形クラス(例:三角形)を追加しても、メインクラスの変更は最小限で済みます。

このコードは、抽象クラス継承多態性動的ディスパッチといったオブジェクト指向プログラミングの主要な概念を実践的に適用しています。これにより、異なる図形の面積を統一的に計算し、出力する柔軟で保守性の高いプログラムが実現されています。

まとめ

  • 多態性とは、同じインターフェースを持つ異なるオブジェクトが、それぞれ独自の方法でそのインターフェースを実装することです。
  • 多態性の主な利点
  1. コードの再利用性の向上
  2. 柔軟性拡張性の増大
  3. 保守性の向上

多態性を適切に使用することで、より柔軟で保守性の高いソフトウェア設計が可能になります。これは特に大規模なシステムや長期的なプロジェクトにおいて重要です。プログラマーは多態性の概念を十分に理解し、適切に適用することで、より効率的で拡張性の高いコードを書くことができます。

未経験でもWEBスキルを取得したい方
  • Javaコース
    Javaプログラミングを基礎から応用まで、体系的に学べる実践的なカリキュラムが特徴です。「マインクラフト」を通じてJavaの基本文法とフレームワークの概念を学びます。また、実際のプロジェクト開発を通じて、データベース連携やWebアプリケーション開発のスキルを身につけることができます。

コメント

タイトルとURLをコピーしました