🎯

【Java】クラス解説21・アップキャスト2

2024/01/18に公開

アップキャスト2のコード例

public class Main {
    public static void main(String[] args) {
        // アップキャスト
        MyClass obj1 = getName(1); // 戻り値:new Fuzi()を受け取り
        MyClass obj2 = getName(2); // 戻り値:new Sakura()を受け取り
        
        // 動的メソッドディスパッチ
        obj1.print(); // 主力結果 -> fuzi
        obj2.print(); // 主力結果 -> sakura
    }
    
    // 戻り値の型がMyClassで、仮引数iの型がint型のgetNameメソッドを定義
    private static MyClass getName(int i) {
        // 引数に応じて異なるインスタンスを戻り値として返すswitch文を使用
        return switch(i) {
            case 1 -> new Fuzi();
            case 2 -> new Sakura();
            default -> new MyClass();
        };
    }
}
// スーパークラスMyClassを定義
class MyClass {
    public void print() {
        System.out.println("MyClass");
    }
}
// サブクラスFuziを定義
class Fuzi extends MyClass{
    // printメソッドをオーバーライド
    public void print() {
        System.out.println("fuzi");
    }
}
// サブクラスSakuraを定義
class Sakura extends MyClass{
    // printメソッドをオーバーライド
    public void print() {
        System.out.println("sakura");
    }
}

コード例の解説

class MyClass {
    public void print() {
        System.out.println("MyClass");
    }
}

スーパークラスのMyClassを定義して、

  1. printメソッドを定義して、
  2. 処理内容は、標準出力にMyClassを出力します。

class Fuzi extends MyClass{
    public void print() {
        System.out.println("fuzi");
    }
}

MyClassを継承したサブクラスFuziを定義して、

  1. スーパークラスのprintメソッドをオーバーライドして、
  2. 処理内容は、標準出力にfuziを出力するよう上書きします。

class Sakura extends MyClass{
    public void print() {
        System.out.println("sakura");
    }
}

MyClassを継承したサブクラスSakuraを定義して、

  1. スーパークラスのprintメソッドをオーバーライドして、
  2. 処理内容は、標準出力にsakuraを出力するよう上書きします。

public class Main {
    public static void main(String[] args) {
        MyClass obj1 = getName(1);
        MyClass obj2 = getName(2);
        
        obj1.print(); // 主力結果 -> fuzi
        obj2.print(); // 主力結果 -> sakura
    }
    private static MyClass getName(int i) {
        return switch(i) {
            case 1 -> new Fuzi();
            case 2 -> new Sakura();
            default -> new MyClass();
        };
    }
}

Mainクラスで、

  1. MyClass型の変数obj1に、実引数で数値の1を渡すgetNameメソッドを呼び出し、その戻り値を代入します。
  2. MyClass型の変数obj2に、実引数で数値の2を渡すgetNameメソッドを呼び出し、その戻り値を代入します。
  3. 戻り値によりFuziクラスのインスタンスが代入された変数obj1からprintメソッドを呼び出すと、Fuziクラスのprintメソッドが呼び出されます。
  4. 戻り値によりSakuraクラスのインスタンスが代入された変数obj2からprintメソッドを呼び出すと、Sakuraクラスのprintメソッドが呼び出されます。
  5. 戻り値の型がMyClassで、仮引数iの型がint型のgetNameメソッドを定義して、
  6. 戻り値としてswitchが使用され、そのswitchの変数iには仮引数の値が代入され、
  7. 1の場合は、Fuziクラスのインスタンスが戻り値として返されます。
  8. 2の場合は、Sakuraクラスのインスタンスが戻り値として返されます。
  9. 1または2以外の場合(=default)は、MyClassクラスのインスタンスが戻り値として返されます。

まとめ

アップキャスト1では、インスタンスの生成を下記の通り記述していました。

Myclass obj1 = new Fuzi();

このアップキャスト2では、インスタンスの生成を下記の通りメソッドや戻り値にswitchを使って記述しました。

MyClass obj1 = getName(1);
MyClass obj2 = getName(2);

private static MyClass getName(int i) {
    return switch(i) {
        case 1 -> new Fuzi();
        case 2 -> new Sakura();
        default -> new MyClass();
    };
}

このような記述であってもポリモーフィズムが働くことが確認できました。

Discussion