ainda na minha jornada incansável no estudo de java me deparei com uma situação da qual não vejo criterio de uso, talvez por imaturidade na linguagem. Seguinte:
então pesquisando rapidamente percebi qeu a solução seria assim:
Funcionario f = new Gerente();
Gerente g = (Gerente)f; // isso daria certo
acontece qeu fiquei martelando com isso na mente, pois, porque alguem digo em que situação um programador iria instanciar a classe gerente no tipo funcionario sendo gerente uma calsse mais especializada e funcionario o mais generico? se tu quer gerente nao faz sentido usar o tipo funcionario pois as funcionalidades de gerente nao estarão visiveis nesta instancia, e se tu instancia a classe gerente é porque tu precisa acessar atributos ou metoos desta classe (gerente) não?
Imaginando a porta de um banco, qualquer funcionário pode entrar na copa por exemplo, até mesmo o gerente…
Agora na sala da gerência é outra história…
Dentro da copa todos se comportam como funcionários certo? Logo você só pode se comunicar como funcionário (métodos específicos declarados em Funcionario), já na sala da gerencia a coisa muda de figura, um gerente pode preparar um relatorio, liberar/bloquear contas, etc (métodos especificos de Gerente)…
Então, …, o que você precisa compreender é que java é uma das linguagens orientadas a objeto. Sua dificuldade não é com java é com a orientação a objeto - OO.
Este tipo de abstração é muito difícil no início, pelo menos no meu caso, pois é mais simples dizer à máquina, faça assim, faça assim, faça assim, fazendo uso do imperativo.
Com orientação a objeto você vai perceber uma redução significativa na quantidade de if, pois objetos com o mesmo comportamento, podem executar ações diferentes.
Respondendo a pergunta:
O gerente é um funcionário?
R: sim.
Logo gerente é um tipo de funcionário, é filho de funcionário, é subclasse de funcionário, ou seja, você pode usar o termo que considerar mais significativo, desde que compreenda a consequência da abstração.
Minha base principal para fins de modelagem são as perguntas é um (para extends) e tem um (para atributo) e assim, aos poucos os objetos vão ganhado sentido.
Se os objetos não possuem sentido a orientação deles é falha.
Ex.: Fusca é um carro -> Ok.
O fusca tem um motor -> Ok.
O motor faz barulho -> Ok.
O motor tem um fusca: sentido prejudicado neste caso, pois é o fusca quem tem um motor que faz barulho.
Se você analisar, vai ver que eu descrevi um objeto, que tem outro objeto, e este último tem um comportamento de forma a preservar o sentido da abstração.
Assim, ao aprender orientação a objeto, você pode utilizar este paradigma em outras linguagens, a exemplo de C#.
Não cabe entregar ao Java o status da orientação a objeto, mas para o utilizar de forma adequada deve conhecer o paradigma que esta e outras linguagens implementam.
Uma orientação tirada de observações pessoais e que me serve bastante é: o retorno importa (o objeto retornado importa).
Sugestão:
Aos 5 minutos e 55 segundos é iniciada a construção de um método que será usado por objetos diferentes.
Você pode perceber que embora sejam animais diferentes, o método os aceita, mas as ações realizadas possuem implementações personalizadas, gerando resultados distintos.
É trabalhoso aprender/entender este paradigma, mas OO é muito legal, pelo menos no meu ponto de vista.