Java 継承２：抽象クラスとポリモフィズムとは

継承には
①スーパークラスを元にフィールドやメソッドをサブクラスに引き継がせて**機能追加**をする方法
②サブクラスが共通して持っているフィールドやメンバ変数、メソッドを元にスーパークラスに**共通点をまとめて**他のサブクラスに継承させる方法
がある。

②の様な方法で継承させる際に共通のメソッドの定義のみをスーパークラスに継承させたメソッド（ System.out.printlnなどの実装内容を持たないメソッド）を**抽象メソッド**、抽象メソッドを一つでも含むクラスは**抽象クラス**と呼ぶ。

また、異なる実装内容を持つオブジェクトを、同一のメソッドで扱うことができること**ポリモフィズム**をと呼ぶ。
ポリモフィズムは、・多様性・多態性・多相性ともいう。

## 抽象クラスと抽象メソッド
・メソッドの定義だけを書いて実装内容（処理の中身）を持たないメソッドを抽象メソッドと呼び、修飾子に**abstract**をつけて定義する。

・クラスの中に一つでも抽象メソッドが含まれているクラスを抽象クラスと呼び修飾子に**abstract**をつけて定義する。
```
アクセス修飾子　abstract class 抽象クラス名{
    // ↓抽象メソッド
    アクセス修飾子 abstract 戻り値の型 抽象メソッド名();
}
//System.out.printlnなどの実装内容や処理は書かない
```
✳︎抽象メソッドには、private/static/final修飾子を付けることはできない。
✳︎アクセス修飾子と戻り値は必要な場合に記述する。


抽象クラスを利用するときは抽象クラスを継承したサブクラスを定義し、抽象メソッドをオーバーライドする。

この書き方（**ポリモフィズム**）で書くメリットは新たにクラスを追加する時に
・メソッドの作成漏れを防ぎ、メソッド名を統一出来るのでプログラムが見やすくなる。
・呼び出す側のクラスの記述を修正しなくて済む。
などがありプログラムの機能を拡張しやすくなる。

### 抽象クラスと抽象メソッドのポイント
・抽象クラスは継承元（スーパークラス）となることが前提のクラス
・抽象メソッドは継承先（サブクラス）でオーバーライドされることで処理内容が確定する。
（「オーバーライドされることで処理内容が確定する」＝「処理内容が確定していないクラス」なのでnewによるインスタンス化ができない）

### 例文
```:実行用クラス
public class StuSample6{
  public static void main(String[] args){
    TandF taf = new TandF("陸上部");
    Football fb = new Football("サッカー部");
    
    Student6 stu1 = new Student6("菅原",taf);
    stu1.display();
    stu1.practice();
    
    Student6 stu2 = new Student6("田仲",fb);
    stu2.display();
    stu2.practice();

  }
}
```
```:抽象クラス（スーパークラス）
public abstract class Club{
  private String name;     // 部活名

  public Club(String name){
    this.name = name;
  }
  public void display(){
    System.out.println("部活動：" + name);
  }
  public abstract void practice();
}
```
```:Clubクラスの情報を扱うクラス
public class Student6{
  private String name;     // 名前
  private Club club;       // Clubオブジェクト

  public Student6(String name, Club club){
    this.name = name;
    this.club = club;
  }
  public void display(){
    System.out.println("名前：" + name);
    club.display();
  }
  public void practice(){
    club.practice();
    System.out.println("------");
  }
}
```
```:サブクラス
public class Football extends Club{
  public Football(String name){
    super(name);
  }
  public void practice(){
    System.out.println("ドリブル");
    System.out.println("シュート練習");
    System.out.println("ミニゲーム");
  }
}
```
```:サブクラス
public class TandF extends Club{
  public TandF(String name){
    super(name);
  }
  public void practice(){
    System.out.println("ウォームアップ");
    System.out.println("インターバル");
    System.out.println("筋トレ");
  }
}
```
```:出力結果
名前：菅原
部活動：陸上部
ウォームアップ
インターバル
筋トレ
------
名前：田仲
部活動：サッカー部
ドリブル
シュート練習
ミニゲーム
------
```
Clubクラスでは10行目で抽象メソッドであるpracticeメソッドを定義している。抽象メソッドを含んでいるのでクラス定義は”public abstract class Club”となる。
Clubクラスはサブクラスで継承して抽象メソッドを上書きして中身を実装する必要がある。この継承しているクラスがFootballクラスとTandFクラスでpracticeメソッドはFootballクラスとTandFクラスで定義されている。

FootballクラスとTandFクラスの両方とも２行目でコンストラクタを定義し、５行目でClubクラスの抽象メソッドであるpracticeメソッドの処理の中身を実装している。

Student６クラスでFootballクラスとTandFクラスの情報をまとめたClubクラスの情報を扱っている。
２行目でメンバ変数、３行目でClubオブジェクトを持たせて、５行目のコンストラクタで受け取っている。
９、１３行目のメソッドでClubクラス側のdisplayメソッドとpracticeメソッドを呼び出している。

StuSampleクラスでは２、３行目で２つのオブジェクトを作ってコンスタントにそれぞれ”陸上部”、”サッカー部”という値を格納し、コンストラクタを呼び出している。
６行目でStudent6 stu1 = new Student6("菅原",taf);とコンストラクタを呼び出しているがtafには”陸上部”という値が格納されているのでStudent６クラスの５行目のコンストラクタのString nameに”菅原”、Club clubに”陸上部”の値が渡される。
なので７行目のdisplayメソッドで”名前：菅原””部活動：陸上部”と出力される
１０行目も同様の処理。

## 参考記事
https://www.youtube.com/watch?v=tfrmaMGJtic&list=PLru8-xuz0YvwUh0FofxilaQ7Tmu_lWyTo&index=7