TRansformar um PAI em um FILHO

Olá galera, tudo bem?

O que eu quero fazer é o seguinte):

Eu crio no meu código uma classe “Aprendiz”. Ele tem 1 trilhão de propriedades, entre elas, pro exemplo, “Pontos_de_Vida”, “Dano” e “Defesa”, tal que essas propriedades irão sendo modificadas constantemente no decorrer do jogo.

Daí, o jogo vai passando e num determinado momento o “Aprendiz” se tornará um “Guerreiro” (Guerreiro é uma classe filha de Aprendiz)

Então, como eu faço pra criar um novo Guerreiro herdando as propriedades (que estavam modificadas) desse Aprendiz ?

Tipo assim: Eu quero “remodelar” esse aprendiz, transfomando-o em um “Guerreiro”, mas mantendo suas “1 trilhão” de propriedades com o mesmo valor, somente ganhando as novas propriedades do “Guerreiro” (que ja estarão setadas com um valor default).

Como poderia fazer isso ?

Por que Guerreiro é filho de Aprendiz? Guerreiro não é um Aprendiz.

Entretanto, ambos Aprendiz e Guerreiro são implementações de uma ClasseDoJogador. Coloque os atributos comuns lá.

Se você tem uma instância ativa de Aprendiz você vai ter que realmente copiar os dados para a instância de Guerreiro que você acabou de criar. A não ser que todos os aprendizer se tornem Guerreiro um dia, então você poderia já ter uma instância de Guerreiro, mas acessada via uma intância de aprendiz, e em um terminado momento você fazia um casting para uma referência do tipo Guerreiro.
Teria algo assim

Aprendiz a = new Guerreiro();
//adicionar os dados para aprender chamando os métodos em a
a.fazCoisasDeAprendiz();

//recebe um evento que transforma aprendiz em guerreiro
Guerreiro g = (Guerreiro)a;
g.fazCoisasDeGuerreiro();

Se não pudermos afirmar que todos Aprendiz se tornará um Guerreiro você pode ter que um Guerrero só pode ser criado se receber uma instância de aprendiz, e copiar estes dados para Guerreiro.

public class Guerreiro extends Aprendiz {
  //variaves de guerreiro
  public Guerreiro(Aprendiz a) {
         setNome(a.getNome()); // metodo da classe Aprendiz
         //outros metodos de aprendiz
         setTipo("Guerreiro");
    }
    //metodos de guerreiro
}

Essas são as soluções que consigo pensar agora.

Algumas linguagens permitem que você altere dinamicamente a classe de um objeto já existente.

Em Java, no entanto, isso infelizmente não existe.

A forma mais estúpida de fazer isso é ter um construtor na classe Guerreiro que recebe um objeto da classe Aprendiz, e copie os campos adequados. O problema, obviamente, é que você vai ter de ficar caçando no seu programa todos os pontos em que esse tal objeto é referenciado, e trocar por uma referência para o novo objeto. Então nem sempre é uma alternativa.

Outra forma é assumir que Guerreiro, Aprendiz etc. são todos Jogadores, e ter apenas objetos da classe Jogador. Entretanto, como você quer ter implementações diferentes para os métodos “lutar”, etc, o que você pode fazer é ter várias classes (HabilidadesGuerreiro, HabilidadesAprendiz etc) que são implementações desses tais métodos. Você então põe um atributo na sua classe Jogador que é uma instância dessa classe Habilidades.
Ao você alterar um jogador de Aprendiz para Guerreiro, você altera só esse atributo.


enum Fase { APRENDIZ, GUERREIRO, ..... };
interface Habilidades {
    void lutar (Jogador j);
}
class HabilidadesGuerreiro implements Habilidades {
     public void lutar (Jogador j) { .... }
}
class HabilidadesAprendiz implements Habilidades {
     public void lutar (Jogador j) { .... }
}
class Jogador {
    private Habilidades hab;
    public void lutar () { hab.lutar (this); }
    ...
    public void evoluiFase (Fase f) {
        switch (f) {
        case APRENDIZ: hab = HabilidadesAprendiz.getInstance(); break;
        case GUERREIRO: hab = HabilidadesGuerreiro.getInstance(); break;
        ...
        }
    }
}
...
Jogador j = new Jogador (Fase.APRENDIZ); // isto faz com que suas habilidades sejam as de um aprendiz
j.lutar(); // j.lutar chama hab.lutar (j); com hab sendo uma instância de HabilidadesAprendiz
j.evoluiFase (Fase.GUERREIRO); 
j.lutar(); // j.lutar chama hab.lutar (j); com hab sendo uma instância de HabilidadesGuerreiro
...

No meu caso, nem sempre um Aprendiz será um Guerreiro… ele poderá ser um Guerreiro, um Mago, um Arqueiro, etc…

(E não conhecia esse “enum”, o que ele faz?

Então não há uma maneira deu transmutar um Aprendiz em qualquer dessas outras classes?

Obrigado!

Todo aprendiz é um jogador
Todo guerreiro, mago, arqueiro é um jogador
Todo jogador pode possuir habilidades de aprendiz, guerreiro, mago ou arqueiro.

Vc não precisa copiar os atributos, apenas adicione mais atributos a classe jogador a medida que o aprendiz evolua.