La risposta di @migliorabile è corretta. Vorrei aggiungere dei consigli che ti posson aiutare con problemi del genere.
In una situazione del genere il punto di partenza è sempre quello di capire chi sono gli attori in gioco, nel tuo caso hai due Player, che possono essere mago, guerriero, ranger… e ragionare sul tipo di relazione che c'è tra di essi.
Nel tuo caso, immagino che “Player” sia un'entità astratta, non qualcosa che realmente poi verrà usato perchè troppo generico.
Potrebbe quindi avere senso pensare di utilizzare un'interfaccia per definire le funzionalità dei Player (metodo per attaccare, per difendere, fare magie…) e utilizzare questa interfaccia per definire le tue classi di gioco. Avrai quindi ad esempio la classe Guerriero che implementa la classe Player. Avendo elencato i metodi obbligatori che ogni player deve avere all'interno dell'interfaccia, nella classe dovrai fornirgli la corretta implementazione.
Utilizzare l'interfaccia ti può anche aiutare a gestire i giocatori all'interno del codice. Ad esempio, non avrai bisogno di un array per i Guerrieri, uno per i Maghi… ma semplicemente un array di “Player”, perchè qualunque sia l'istanza dell'oggetto che peschi dall'array, questo ha sicuramente i metodi attacca e difendi definiti (anche se ognuno a modo suo).
L'interfaccia potrebbe essere per esempio definita in questo modo:
interface Player {
public void attack(Player defender);
public void defend(int damage, String attackType);
}
Poi ogni classe avrà la propria implementazione, tipo:
class Guerriero implements Player {
//... attributi ...
private int hp = 500;
private final int maxDamage = 100;
private final String attackType = "spada";
public void attack(Player defender) {
int damage = (int) (Math.random() * maxDamage);
defender.defend(damage, attackType);
}
public void defend(int damage, String attackType) {
//... gestisci l'attack type...
this.hp -= damage;
}
}
Per l'idea della superclasse (quindi una classe che viene ereditata da player) non ha molto senso, penso ti sia confuso con questo concetto :P
La classe CombatSystem potrebbe essere una classe che non estende né implementa Player, ma semplicemente ha dei metodi per gestirli (tipo utilizzando un sistema a turni) ad esempio un metodo del genere:
class CombatSystem {
public void avviaCombattimento(Player attaccante, Player difensore) {
while(true) {
attaccante.attack(difensore);
Thread.sleep(1000); // qui manca un throws o un try-catch
}
}
}