Uma coisa que percebi é que se pudéssemos mudar a classe em tempo de execução isso resolveria alguns problemas de modelagem.
Um dos problemas é o seguinte: digamos que você tenha um objeto do tipo Aprendiz, que foi promovido a Guerreiro. (E tenha a hierarquia Jogador -> Aprendiz -> Guerreiro -> General -> Rei, por exemplo).
Ele tem alguns atributos adicionais (até aí tudo bem), mas o problema é que eu não posso simplesmente pegar o tal objeto do tipo Aprendiz e copiá-lo para um objeto do tipo Guerreiro, senão eu teria de ficar procurando TODAS as referências a ele no programa, para substituí-las por esse novo objeto (ou seja, você deveria poder morrer para ressuscitar , mas o problema é que, devido às referências, você não consegue morrer para poder ser substituído).
Como vocês viram, deve ser melhor separar essa parte do papel que um determinado objeto desempenha, e separá-lo em um atributo. Ou seja, há só uma classe Jogador, que não tem descendentes, mas há várias classes derivadas de Papel, por exemplo PapelAprendiz, PapelGuerreiro, PapelGeneral e PapelRei.
Quando você precisar promover um Jogador de aprendiz para guerreiro, você só altera o atributo Papel, com um objeto da classe adequada (PapelGuerreiro) contendo os atributos necessários para um guerreiro.