抽象クラスのメリット

抽象クラスの使いどころと聞いて何を思い浮かべるでしょうか？
インターフェイスを使っていると、抽象クラスの存在は霞んでしまいがちです
しかし、明確なメリットもあります
それは...

* **動的なフィールドを持てる事**

インターフェースには無い明確な個性です
何故なら、抽象クラスに対しインターフェイスは静的なインスタンスであるため、動的フィールドを自身で運用できないためです
抽象クラスは、これを高度に隠ぺいします

<details><summary>コード一覧</summary>

```:Status.java
public abstract class Status{
        private int hp,atk;

        public Status(int hp,int atk){
                this.hp=hp;
                this.atk=atk;
        }

        protected void damage(Status target){
                int currentHP=0;
                target.hp=(currentHP=target.hp-this.atk)>=0?currentHP:0;
        }

        public void currentHP(){
                System.out.println(this+":"+this.hp);
        }
}
```
```:Fighter.java
public abstract class Fighter<T extends Status> extends Status{
        public Fighter(int hp,int atk){
                super(hp,atk);
        }

        public void attack(T target){
                super.damage(target);
        }
}
```
```:Player.java
public class Player extends Fighter<Enemy>{
        public Player(int hp,int atk){
                super(hp,atk);
        }
}
```
```:Enemy.java
public class Enemy extends Fighter<Player>{
        public Enemy(int hp,int atk){
                super(hp,atk);
        }
}
```
</details>

```:Main.java
public class Main{
        public static void main(String[] args){
                Player player=new Player(100,20);
                Enemy enemy=new Enemy(100,10);

                for(int i=10;i>0;--i)
                        player.attack(enemy);

                enemy.currentHP();
        }
}
```
```:結果
Enemy@27716f4:0
```
基本的なステータスを管理する抽象クラスとして```Status```を定義します
これはクラスなので、プライベートなフィールドを持つことが出来ます
受け取ったインスタンスが```Status```型であれば自身のフィールドへアクセスできるので、これを操作するメソッドを定義できます
ここでは```damage```メソッドで操作します
```:Status.java
public abstract class Status{
        private int hp,atk;

        public Status(int hp,int atk){
                this.hp=hp;
                this.atk=atk;
        }

        protected void damage(Status target){
                int currentHP=0;
                target.hp=(currentHP=target.hp-this.atk)>=0?currentHP:0;
        }

        public void currentHP(){
                System.out.println(this+":"+this.hp);
        }
}
```
```damage```メソッドは```protected```なため、子クラスで呼び出すことが出来ます
しかし```Status```と継承関係にないクラスからは呼び出せません
これによりインスタンスのパラメータに外部からはアクセスできないよう制限を設けることができます

```:Fighter.java
public abstract class Fighter<T extends Status> extends Status{
        public Fighter(int hp,int atk){
                super(hp,atk);
        }

        public void attack(T target){
                super.damage(target);
        }
}
```
```attack```メソッドには型引数```T```が定義されています
子クラスとなる以下の```Player```と```Enemy```でこの型引数にクラスを指定することで、引数の型を各インスタンスごとに**変更**することが出来ます
```:Player.java
public class Player extends Fighter<Enemy>{
        public Player(int hp,int atk){
                super(hp,atk);
        }
}
```
```:Enemy.java
public class Enemy extends Fighter<Player>{
        public Enemy(int hp,int atk){
                super(hp,atk);
        }
}
```
例えば現在```Player```クラスから呼び出し可能な```attack```メソッドは、親クラスである```Fighter```の型引数に```Enemy```を指定しているため、```Enemy```型以外のインスタンスを受け付けません
そのためこのメソッドに```Player```のインスタンスを代入すると**構文エラー**を報告します
```:Main.java
public class Main{
	public static void main(String[] args){
		Player player=new Player(100,20);
		Enemy enemy=new Enemy(100,10);

		for(int i=10;i>0;--i)
			player.attack(player);

		enemy.currentHP();
	}
}
```
```:結果
Main.java:7: エラー: 不適合な型: PlayerをEnemyに変換できません:
                        player.attack(player);
```
このように、抽象クラスを用いることでパラメータがより厳格に保護されます

インスタンスが動的であることは、それ自体が一つの利点であると言えます
抽象クラスはそれ単体のインスタンス化を禁止したい場面でも役立ちます
今回のようにメソッドの適用対象を限定したいケースでは、あるクラスを継承することが確実に保証される手段として有用です