[quote=pimenta]Pelo visto o meu “cursinho básico de OO” foi um bosta mesmo, pois não citaram ganhos mais importantes para usar herança que não fossem reutilização de código e manutenção de código.
Se possível gostaria que me informasse qual/quais os efeitos primários da utilização de herança, visto que, como você disse, reutilização é secundário.
Herança não é remédio para a preguiça, mas é remédio para ganho de produtividade, ganho de tempo. E ambos estão inerentes ao desenvolvimento.
E aqui a questão não é aceitar ou não aceitar sua palavra. Estamos em um forum, o qual é voltado pra discussão, portanto, subentende-se que cada um pode expressar sua opinião pra que a mesma possa ser discutida. Não estou convencido que usar herança no problema do amigo é uma “fuga” do enunciado, mas gostaria que me convencessem disso.
[/quote]
Não disse que era um fuga. Apenas chamei a atenção para que; usar herança para apenas reaproveitar codigo é uma má prática. E para terem cuidado com esse tipo de modelagem. Como isto é um forum básico, o meu objetivo foi só chamar a atenção.
O uso de herança é restrito à necessidade de polimorfismo. Ou seja, quando eu quero tratar coisas diferentes como se fossem iguais. Normlmente eu preciso abstrair essas coisas diferentes e encontrar uma parente comum.
Se o modelo tivesse necessidade de um processo fazAlgumaCoisaAAluno(Aluno a) e depois um outro fazAlgumaCoisaAProfessor(Professor pf) e um outro fazAlgumaCoisaAFuncionario(Funcionario f) e o que o processo fizesse fosse exactamente a mesma coisa, ou apenas ligeiramente diferente ( um if de diferença) seria util inventar um fazAlgumaCoisaA(Pessoa p). Nestas circusntancias, e apenas nestas circunstancias, em que tenho necessidade de algo mais abstrato é que eu coloca o tipo Pessoa na mistura. E para começar ela é uma interface ( programação para interface). Não necessito de mais do que aquilo que uma interface me dá. Não preciso saltar direto para herança de classe.
Conforme novos processo vão sendo descobertos e à medida de que a necessidade cresce pode ser necessário tornar Pessoa uma classe em vez de um interface. Um motivo simples é: Aquilo que é pessoa não pode ser nada mais. Então ai, quando eu sei que posso gastar a minha única herança , eu crio Pessoa como uma classe abstrata e faço Aluno, etc… herdar dela.
Houve reaproveitamento de código aqui ? Sim. eu reaproveitei tudo o codigo dentro de fazAlgumaCoisaA() , tenho ganho em produtividade e manutenção ? sim. Só tenho um único método e só tenho que manter um único método. Houve alguma tentativa de aproveitar/fundir codigo dentro das classes Aluno, Professor, etc… ? Não. Não houve.
O ganho mais importante é polimorfismo. Com o polimorfismo vc obtem outros ganhos de forma natural pela propria estrutrua do java e da OO, mas eu não procurei usar herança para agrupar atributos comuns de aluno, professor, etc… eu a usei para facilitar a escrita de fazAlgumaCoisaA()
Como no modelo do topico não existe esse método que necessite de algo polimorfico, não ha porquê usar herança.
Agora vc me diz : mas todos têm cpf, nome, etc… não dá para agrupar isso ?
Sim, dá. Vc cria uma classe DadosDemograficos e coloca tudo isso lá. Ai, cada classe dessas terá um DadosDemograficos em vez de N atributos. Isso pode ser suficiente em muitos mais casos do que imagina. E sem recorrer a herança.
Agora que entendeu, imagine que o fazAlgumaCoisa era enviaEmailPara() eu preciso de saber o endereço e o nome da pessoa para quem estou enviando. Será que o meu DadosDemograficos resolve ? sim, resolve
class XPTO {
public void enviaEmailPara( DadosDemograficos dd ) {
Email email = new Email() // classe ficiticia
email.setAddress( dd.getEmail());
email.setText("Olá , " + dd.getName() );
email.send();
}
}
Sem herança eu tenho apenas um só método que serve para todos os tipos de “pessoa”.
Agora que vc entendeu isso vc me diria: EnviaEmailPara(DadosDemograficos) é meio estranho, envian-se emaisl para pessoas.
Ok, então crie a interface Pessoa assim
interface Pessoa {
public DadosDemograficos getDadosDemograficos();
}
e faça Aluno, etc… implementá-la. Altere o método para receber Pessoa e puxe os dados demograficos dentro do método.
Isto não altera em nada o que as suas classes já faziam ( elas já tinham esse método) mas vc ganhou polimorfismo.
Isto é um exemplo simples. O ponto é que herança é algo muito mais forte e poderoso do que se pode pensar à primeira vista.
Por isso que a herança não é multipla em java. É um recurso de ultimo recurso. É aquela arma que vc guarda para enfrentar o boss no fim do jogo. Se vc a usa cedo demais, depois vc se ferra.
Java lhe dá muitas mais ferramentas do que herança, e mais baratas. Então use-as. Não se precipite a usar herança só porque vc vê atributos comuns em uma classe.
Bom, dito tudo isto: vc poderia em vez de chamar de DadosDemograficos chamar diretamente de Pessoa. Que foi o que o modelo original fez. O objetivo de criar aquela classe é agrupar atributos e isso não se resolve com herança. Por isso o modelo é válido.
Mas usar o nome “Pessoa” para essa classe de agrupamento cria uma confusão automática pq a palavra “Pessoa” transmite um conceito de herança quase que automáticamente. E dai toda esta confusão. Por isso que modelar não é tão simples quanto parece… 
Conceitos são mais importantes que palavras. Quando vc vir “Pessoa” em um modelo pense: o que está sendo feio ali ? Agrupar atributos ? Então não deve ser usada herança. Pelo menos não sem uma muito boa razão. Só o resto do modelo lhe pode dar essa razão.
No caso do enunciado, não ha essa razão