☕ Side.java

public enum Side {
    RED("레드"), BLUE("블루");
    private String name;

    Side(String name) { this.name = name; }

    public String getName() { return name; }
}

☕ Unit.java

public abstract class Unit {
    
		//  ⚠️ 이후 실습의 편의를 위해 일부 필드를 public으로
    //  - 실무에서는 private로 만들고 getter/setter 권장
    public Side side;
    public int hp;

    public Unit(Side side, int hp) {
        this.side = side;
        this.hp = hp;
    }

		public Side getSide() {
        return side;
    }
}

☕ Attacker.java

public interface Attacker {
    void defaultAttack(Unit target);
}

☕ Swordman.java

public class Swordman extends Unit implements Attacker {
    public Swordman(Side side) {
        super(side, 80);
    }

    private void swordAttack(Unit target) {
        target.hp -= 10;
    }

    @Override
    public void defaultAttack(Unit target) {
        swordAttack(target);
    }

		@Override
    public String toString() {
        return side.toString() + " 진영 검사";
    }
}

☕ Knight.java

public class Knight extends Swordman {
    private enum Weapon { SWORD, SPEAR }
    private Weapon weapon = Weapon.SWORD;

    public Knight(Side side) {
        super(side);
        hp += 40;
    }

    public void switchWeapon () {
        weapon = weapon == Weapon.SWORD ? Weapon.SPEAR : Weapon.SWORD;
    }

    private void spearAttack(Unit target) {
        target.hp -= 14;
    }

    @Override
    public void defaultAttack(Unit target) {
        if (weapon == Weapon.SWORD) {
            super.defaultAttack(target);
        } else {
            spearAttack(target);
        }
    }

		@Override
    public String toString() {
        return side.toString() + " 진영 기사";
    }
}

☕ MagicKnight.java

public class MagicKnight extends Knight {
    public int mana = 60;
    public final int MANA_USAGE = 4;
    public MagicKnight(Side side) {
        super(side);
    }

    public void lighteningAttack (Unit[] targets) {
        for (Unit target : targets) {
            if (target instanceof MagicKnight) continue;
            if (mana < MANA_USAGE) break;
						System.out.printf("⚡️ → 💀 %s%n", target);
            target.hp -= 8;
            mana -= MANA_USAGE;
        }

    }

		@Override
    public String toString() {
        return side.toString() + " 진영 마법기사";
    }
}

☕ Horse.java

public class Horse<T extends Unit> {
    private int extraHp;
    private T rider;

    public Horse(int extraHp) {
        this.extraHp = extraHp;
    }

    public void setRider(T rider) {
        this.rider = rider;
        rider.hp += extraHp;
    }

		@Override
    public String toString() {
        return "말 (추가체력: %d)".formatted(extraHp);
    }
}

☕ Main.java

				Swordman r_swordman1 = new Swordman(Side.RED);
        Knight r_knight1 = new Knight(Side.RED);
        Knight r_knight2 = new Knight(Side.RED);
        MagicKnight r_magicKnight1 = new MagicKnight(Side.RED);

        Knight b_knight1 = new Knight(Side.BLUE);
        MagicKnight b_magicKnight1 = new MagicKnight(Side.BLUE);
        MagicKnight b_magicKnight2 = new MagicKnight(Side.BLUE);

        Horse<Swordman> avante = new Horse<>(40);
        Horse<Knight> sonata = new Horse<>(50);

        avante.setRider(r_swordman1); // 🔴
        sonata.setRider(b_magicKnight1);

        r_swordman1.defaultAttack(b_knight1); // 🔴
        r_knight1.defaultAttack(b_magicKnight1);
        r_knight2.switchWeapon();
        r_knight2.defaultAttack(b_magicKnight2);

        b_magicKnight1.defaultAttack(r_swordman1);
        b_magicKnight2.lighteningAttack(new Unit[] {
                r_knight1,
                r_knight2,
                r_magicKnight1
        });