Java の継承とポリモーフィズム

JavaJavaBeginner
オンラインで実践に進む

はじめに

この実験では、Java におけるオブジェクト指向プログラミングの 2 つの基本概念である継承とポリモーフィズムを探ります。これらの強力な機能により、より組織的で効率的で柔軟なコードを作成することができます。まずは継承を探り、既存のクラスを基に新しいクラスを作成することができるようになり、次にポリモーフィズムに移り、異なるクラスのオブジェクトを統一的に扱うことができるようになります。

この実験が終了すると、以下のことができるようになります。

  1. 継承を使ってクラス階層を作成する
  2. サブクラスでメソッドをオーバーライドする
  3. ポリモーフィズムを理解して使用する
  4. 抽象クラスと抽象メソッドを実装する

これらの用語が複雑に聞こえる場合は心配しないでください。すべてを簡単で分かりやすい手順に分解します。Java プログラミングスキルを向上させる刺激的な旅に始めましょう!

これは Guided Lab です。学習と実践を支援するためのステップバイステップの指示を提供します。各ステップを完了し、実践的な経験を積むために、指示に注意深く従ってください。過去のデータによると、この 初級 レベルの実験の完了率は 94%です。学習者から 100% の好評価を得ています。

基底クラスの作成

まずは、Animal という名前の基底クラスを作成します。このクラスは他のクラスの基礎となります。

  1. ターミナルを開き、プロジェクトディレクトリに移動します。

    cd ~/project
  2. touch コマンドを使って、Animal.java という新しいファイルを作成します。

    touch Animal.java
  3. テキストエディタで Animal.java を開き、次のコードを追加します。

    public class Animal {
        private String name;
        private int age;
    
        public Animal(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public void eat() {
            System.out.println(name + " is eating.");
        }
    
        public void sleep() {
            System.out.println(name + " is sleeping.");
        }
    
        public String getName() {
            return name;
        }
    
        public int getAge() {
            return age;
        }
    }

    このコードを分解してみましょう。

    • Animal という名前のクラスを定義し、2 つの属性 name(文字列型)と age(整数型)を持ちます。
    • private キーワードは、これらの属性がクラス内でのみアクセス可能であることを意味します。
    • Animal オブジェクトが作成されるときにこれらの属性を初期化するコンストラクタがあります。
    • eat()sleep() の 2 つのメソッドがあり、動物が何をしているかを表示します。
    • クラスの外から private 属性にアクセスできるようにする "getter" メソッド (getName()getAge()) もあります。
  4. Animal.java ファイルを保存します。

Saving Animal java file
  1. 次に、Animal クラスをコンパイルしてエラーがないことを確認しましょう。ターミナルで次のコマンドを実行します。

    javac Animal.java

    エラーメッセージがなければ、クラスのコンパイルは成功です!

サブクラスの作成

基本クラスである Animal ができたので、Dog というサブクラスを作成してみましょう。これにより、Java における継承の仕組みを説明します。

  1. ターミナルで、Dog.java という新しいファイルを作成します。

    touch Dog.java
  2. テキストエディタで Dog.java を開き、以下のコードを追加します。

    public class Dog extends Animal {
        private String breed;
    
        public Dog(String name, int age, String breed) {
            super(name, age);  // スーパークラスのコンストラクタを呼び出す
            this.breed = breed;
        }
    
        public String getBreed() {
            return breed;
        }
    }

    この新しいコードを詳しく見ていきましょう。

    • extends Animal は、DogAnimal のサブクラスであることを Java に伝えます。DogAnimal から継承しますが、Animal のプライベート属性である nameage は、Dog 内で直接アクセスすることはできません。しかし、Dog は継承されたパブリックな getter メソッドである getName()getAge() を介してこれらの属性にアクセスできます。
    • Dog に固有の新しい属性 breed を追加しました。
    • コンストラクタは 3 つのパラメータを取ります。super(name, age) を使用して Animal コンストラクタを呼び出し、次に breed を設定します。
    • Dog に固有の新しいメソッド getBreed() を追加しました。
  3. Dog.java ファイルを保存します。

  4. Dog クラスをコンパイルします。

    javac Dog.java

    Animal.class に関する警告が表示されるかもしれませんが、今のところ問題ありません。

継承の実証

Animal クラスと Dog クラスができたので、継承がどのように機能するかを示すプログラムを作成しましょう。

  1. InheritanceDemo.java という新しいファイルを作成します。

    touch InheritanceDemo.java
  2. InheritanceDemo.java を開き、次のコードを追加します。

    public class InheritanceDemo {
        public static void main(String[] args) {
            Animal genericAnimal = new Animal("Generic Animal", 5);
            Dog myDog = new Dog("Buddy", 3, "Labrador");
    
            System.out.println("Demonstrating Animal class:");
            genericAnimal.eat();
            genericAnimal.sleep();
    
            System.out.println("\nDemonstrating Dog class:");
            myDog.eat();  // Animalから継承
            myDog.sleep();  // Animalから継承
    
            System.out.println("\nDog details:");
            System.out.println("Name: " + myDog.getName());  // 継承されたメソッド
            System.out.println("Age: " + myDog.getAge());  // 継承されたメソッド
            System.out.println("Breed: " + myDog.getBreed());  // Dog固有のメソッド
        }
    }

    このプログラムは、Animal クラスと Dog クラスの両方のインスタンスを作成し、Dog クラスが Animal クラスからメソッドを継承する方法を示しています。

  3. InheritanceDemo.java ファイルを保存します。

  4. プログラムをコンパイルして実行します。

    javac InheritanceDemo.java
    java InheritanceDemo

    次のような出力が表示されるはずです。

    Demonstrating Animal class:
    Generic Animal is eating.
    Generic Animal is sleeping.
    
    Demonstrating Dog class:
    Buddy is eating.
    Buddy is sleeping.
    
    Dog details:
    Name: Buddy
    Age: 3
    Breed: Labrador

この実証は、Dog クラスが Animal クラスから属性とメソッドを継承する一方で、独自の固有の属性 (breed) とメソッド (getBreed()) を追加する方法を示しています。

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

メソッドのオーバーライドは、サブクラスがスーパークラスに既に定義されているメソッドの特定の実装を提供できる機能です。これがどのように機能するか見てみましょう。

  1. Dog.java を開き、次のメソッドを追加します。

    @Override
    public void eat() {
        System.out.println(getName() + " is eating dog food.");
    }

    このメソッドを Dog クラスの内部で、他のメソッドの外に追加します。

    @Override アノテーションは、コンパイラに対して、スーパークラスのメソッドをオーバーライドすることを意図していることを伝えます。必須ではありませんが、使用するのは良い慣例です。

  2. Dog.java ファイルを保存します。

  3. 次に、メソッドのオーバーライドを示すために InheritanceDemo.java を変更しましょう。InheritanceDemo.java を開き、その内容を次のものに置き換えます。

    public class InheritanceDemo {
        public static void main(String[] args) {
            Animal genericAnimal = new Animal("Generic Animal", 5);
            Dog myDog = new Dog("Buddy", 3, "Labrador");
    
            System.out.println("Demonstrating method overriding:");
            genericAnimal.eat();
            myDog.eat();
    
            System.out.println("\nDemonstrating inherited method:");
            myDog.sleep();  // このメソッドは依然としてAnimalから継承されています
    
            System.out.println("\nDog details:");
            System.out.println("Name: " + myDog.getName());
            System.out.println("Age: " + myDog.getAge());
            System.out.println("Breed: " + myDog.getBreed());
        }
    }
  4. InheritanceDemo.java ファイルを保存します。

  5. 更新されたプログラムをコンパイルして実行します。

    javac Animal.java Dog.java InheritanceDemo.java
    java InheritanceDemo
Method overriding output example

次のような出力が表示されるはずです。

Demonstrating method overriding:
Generic Animal is eating.
Buddy is eating dog food.

Demonstrating inherited method:
Buddy is sleeping.

Dog details:
Name: Buddy
Age: 3
Breed: Labrador

これは、メソッドのオーバーライドが Dog クラスに eat() メソッドの独自の実装を提供する一方で、Animal クラスから sleep() のような他のメソッドを継承し続ける方法を示しています。

ポリモーフィズムの紹介

ポリモーフィズムはオブジェクト指向プログラミングにおける基本的な概念で、基底クラスの参照を使ってサブクラスのオブジェクトを参照できるようにします。これにより、より柔軟で再利用可能なコードが可能になります。どのように機能するか見てみましょう。

  1. Cat.java という新しいファイルを作成します。

    touch Cat.java
  2. Cat.java を開き、次のコードを追加します。

    public class Cat extends Animal {
        public Cat(String name, int age) {
            super(name, age);
        }
    
        @Override
        public void eat() {
            System.out.println(getName() + " is eating fish.");
        }
    
        public void meow() {
            System.out.println(getName() + " says: Meow!");
        }
    }

    これは、独自の eat() メソッドと新しい meow() メソッドを持つ Animal の別のサブクラスを作成します。

  3. Cat.java ファイルを保存します。

  4. 次に、ポリモーフィズムを示すために InheritanceDemo.java を更新しましょう。その内容を次のものに置き換えます。

    public class InheritanceDemo {
        public static void main(String[] args) {
            Animal[] animals = new Animal[3];
            animals[0] = new Animal("Generic Animal", 5);
            animals[1] = new Dog("Buddy", 3, "Labrador");
            animals[2] = new Cat("Whiskers", 2);
    
            System.out.println("Demonstrating polymorphism:");
            for (Animal animal : animals) {
                animal.eat();  // これは各動物に適切なeat()メソッドを呼び出します
            }
    
            System.out.println("\nAccessing specific methods:");
            ((Dog) animals[1]).getBreed();  // Dog固有のメソッドを呼び出すにはDogにキャストする必要があります
            ((Cat) animals[2]).meow();      // Cat固有のメソッドを呼び出すにはCatにキャストする必要があります
        }
    }

    このコードは Animal オブジェクトの配列を作成しますが、実際にはその中に AnimalDogCat のオブジェクトの混合物を格納しています。各動物に対して eat() を呼び出すと、Java はオブジェクトの実際の型に基づいて適切なメソッドのバージョンを自動的に呼び出します。

  5. InheritanceDemo.java ファイルを保存します。

  6. 更新されたプログラムをコンパイルして実行します。

    javac Animal.java Dog.java Cat.java InheritanceDemo.java
    java InheritanceDemo

    次のような出力が表示されるはずです。

    Demonstrating polymorphism:
    Generic Animal is eating.
    Buddy is eating dog food.
    Whiskers is eating fish.
    
    Accessing specific methods:
    Whiskers says: Meow!

これはポリモーフィズムの実際の動作を示しています。すべてのオブジェクトを Animal オブジェクトとして扱うことができますが、eat() メソッドを呼び出すと、各オブジェクトはその特定のクラスの実装に従って動作します。

まとめ

この実験では、Java におけるオブジェクト指向プログラミングのいくつかの重要な概念を探りました。

  1. 継承:基底の Animal クラスを作成し、それから Dog クラスと Cat クラスを派生させました。これにより、コードの再利用が可能になり、クラスの論理的な階層構造を作成できました。
  2. メソッドのオーバーライド:サブクラスがスーパークラスに定義されたメソッドの独自の実装を提供できる方法を見ました。これにより、より具体的な動作が可能になります。
  3. ポリモーフィズム:異なるクラスのオブジェクトをそれらの共通のスーパークラスを通じて一様に扱う方法を学びました。これにより、より柔軟で再利用可能なコードが可能になります。

これらの概念は、Java や一般的なオブジェクト指向プログラミングにとって基本的なものです。これらを使うことで、より組織的で効率的で柔軟なコード構造を作成できます。Java の学習を続けるにつれて、これらの概念がより複雑なアプリケーションで広く使用されていることに気付くでしょう。

覚えておいてください。これらの概念をマスターするキーは練習です。

Morty Proxy This is a proxified and sanitized view of the page, visit original site.