JavaSilver受験者は必ずマスターしよう！ポリモーフィズムの考え方

この記事は、[シアトルコンサルティング株式会社](https://qiita.com/advent-calendar/2021/seattleconsulting) Advent Calendar 2021の10日目の記事です。
こんにちは、シアトルコンサルティングの森です。
TeamTech Move the WorldをMissionに掲げ、日々全力で業務に取り組んでおります！
少しでも興味を持って頂けたら下記のサイトを覗いてみてください！

コーポレートサイト
https://www.seattleconsulting.co.jp/
Wantedly
https://www.wantedly.com/companies/seattleconsulting
よろしくお願い致します！
## はじめに
今回はJavaSilverを取得する上で押さえておきたい概念「ポリモーフィズム」について、
実際の問題とともに説明していきます。
この記事を読んでポリモーフィズムに関する問題や考え方をマスターしていただければ幸いです。

## 目次
- そもそもポリモーフィズムとは
- 具体的な問題の出題方法
- ポイント（フィールド、オーバーライド、オーバーロード）
- まとめ  
- 最後に

## そもそもポリモーフィズムとは  
>ポリモーフィズムは「多態性」などとも言われ，１つのインターフェースに対して複数の異なる振る舞いをする実装を作成できる機構のことである。（https://www.ipa.go.jp/security/awareness/vendor/programmingv1/a03_04_main.html）
>

と言われても「ほぉ」としかならないと思います。
一言で言うと、「同じ関数でも入れる変数によって違う処理を行える」といったところです。
またポリモーフィズムはオブジェクト指向三大特長（カプセル化、継承、ポリモーフィズム）であります。

では実際にどのように使用されるかというと、継承や実現とともに使われます。
その上で以下の場合によく問題として使用されます。

- スーパークラスとサブクラスに同名のフィールドやメソッドが存在する
- インスタンス生成の型と実装が異なる

では具体的なコードを見ていきましょう。

## 具体的な問題の出題方法
####①フィールド

```java:
class A{  
    String str = "Apple";  
    void print(){
        System.out.println(str);
    }
}
class B extend A{  
    String str = "Orange"
}
public class main{
public static void main(String[]args){
    A a = new A();
    A b = new B();
    System.out.println(a.str);
    System.out.println(b.str);
    a.print();
    b.print();
    }
}
```

上記のようなコードの場合どういった内容が表示されるのか。
AクラスとBクラスには同名のフィールド「str」が存在します。
こうなったときにAクラスのstrが表示されるのか、Bクラスのstrが表示されるのか、
結論から言うと出力結果は **「AppleAppleAppleApple」**です。

どの変数が使われるかはインスタンスの実装の型ではなく、**参照の型**で決まります
今回で言うと、
A a = new Bというインスタンス生成はB型のインスタンスを**A型で扱うということ**なので、
Aのフィールドを扱うことになります。

またprint（）メソッドはAクラスにしか存在しません。そのためAクラスに定義されているvalを使用することとなります。
####②オーバーライド・オーバーロードされたメソッド
次はスーパークラスのメソッドをオーバーライドし、サブクラスのインスタンスをスーパークラス型で扱ったときにどちらのメソッドを使用するのかという問題で、

```java:example
public class A{
    public void sample (){
        System.out.println("スーパークラスのメソッドです");
    }
}
public class B extends A{
    public void sample(){
        System.out.println("オーバーライドしたメソッドです");
    } 
    public void sample(int num){
        System.out.println("オーバーロードしたメソッドです");
    }
} 
public class Main{
    public static void main(String[]args){
        A a1 = new A();
        A a2 = new B();
        B b  = new B();

        a1.sample();
        a2.sample();
        b.sample(3);
    }
}
```
上記のようなコードの様に、
スーパークラスのメソッドをサブクラスでオーバーライドし、さらにそれをオーバーロードしたクラスがあるとします。
そして、先ほどと同じくインスタンスの型と実装が異なる場合はどちらのメソッドを使用するのだろうか。
コンパイル結果は、

```java:console
スーパークラスのメソッドです
オーバーライドしたメソッドです
オーバーロードしたメソッドです
```
となります。

B型のインスタンスをA型として扱った時A型に定義されているsampleメソッドを探しますが、Bクラスで**オーバーライドされている場合はオーバーライドされている方のメソッドを使用します。**そのため、「a2.sample()」をコンパイルすると「オーバーライドしたメソッドです」と表示されます。
また注意点として、この時Aクラスにsampleメソッドがなく、sampleメソッドが新たにBクラスで定義された場合に「a2.sample();」をコンパイルするとコンパイルエラーとなるので注意してください。参照の型に存在しないものを使用するとコンパイルエラーになります。


また「b.sample(int num);」の様にオーバーライドしたものは通常通り扱えますが、上記で説明した通り「a2.sample(3);」とコンパイルするとAクラスにはint型引数を必要としたsampleメソッドはないためコンパイルエラーとなります。

## まとめ

継承関係や実現関係などが存在し、インスタンス生成の型と参照の型が違いポリモーフィズムが使用される場合

##### フィールドは参照先のに定義されているものを使用
##### メソッドはまず、参照先に定義されているかどうかを確認　　
→　定義されていなければコンパイルエラー
#####定義されているがインスタンス生成の型のクラスでオーバーライドされていたら、そちらを使用

## 最後に

ポリモーフィズムがわからないとJavaSilver取得は非常に厳しくなるので必ずマスターして受験に臨んでください。
またポリモーフィズムは概念の話なので、今回の記事の内容がポリモーフィズムとは思わないでください。
こちらはあくまでJavaSilverの試験内でポリモーフィズムを利用した問題です。