Olá pessoal.
Continuando a serie de topicos do tipo “Por que java não XXX” http://www.guj.com.br/posts/list/65469.java#344793
agora é a vez de herança multipla.
Por que naum por herança multipla no java… tipo do que eles tem medo que saiam anomalias dos sistemas…
Não é errado isto da linguagem presumir que voce é um idiota então proibir tudo que possa causar confusão.
Afinal em nenhuma hipotese seria util modelar algo com herança multipla…
Gostaria da opnião de voces…
Grato.
[quote=AndrewAguiar]Olá pessoal.
Continuando a serie de topicos do tipo “Por que java não XXX” http://www.guj.com.br/posts/list/65469.java#344793
agora é a vez de herança multipla.
Por que naum por herança multipla no java… tipo do que eles tem medo que saiam anomalias dos sistemas…
Não é errado isto da linguagem presumir que voce é um idiota então proibir tudo que possa causar confusão.
Afinal em nenhuma hipotese seria util modelar algo com herança multipla…
Gostaria da opnião de voces…
Grato. [/quote]
Lei de Murphy: Tudo o que poder dar errado, vai dar errado.
Se vc libera a HM algo vai dar errado. Isso foi provado com C++ ( assim como manipular ponteiros directamente) e foi removido em Java. Java sim é um linguagem que defende melhores formas de programação
e portanto elimina tudo o que pode causar anomalias. Não necessáriamente presume que o programador é idiota.Ela presume que o programador comete erros , e certos erros são idiotas. Por exemplo, a palavra chave “goto” é reservada em Java exatamente para que não seja usada.
Como não encontrei nada que não pude fazer em Java por falta de herança múltipla, não me atrapalha o fato de não tê-la.
Talvez algumas coisas até fosse facilitadas com ela, mas tudo que encontrei foi possível de ser resolvido de outra maneira.
Mais no caso da herança multipla não tem como cometer erros… ou o cara modela com HM ou não. Penso q isso de “evitar que o programador se confunda”, apenas tira flexibilidade.
como vc mesmo disse " Afinal em nenhuma hipotese seria util modelar algo com herança multipla… "
Então, se não vou usar, para quê colocar ?
Lembre-se que herança nem sempre serve para modelar, às vezes serve so para reaproveitar codigo.
Como java isa HM simples, modelar implica em reaproveitar codigo e vice-versa. Já com HM nem sempre um implica o outro e ai que são criados os problemas.
Alguem acredita realmente que o fato do java não suportar herança multipla tem haver com tornar os programas mais seguros?
Me parece ser uma questão de design.
Agora se uma classe pode extender uma outra classe e implementar diversas interfaces, não vejo motivo para não poder extender muitas classes (Só não consigo entender como o super() iria funcionar nesse caso, a menos que haja apenas uma classe “principal”, enfim…).
como vc mesmo disse " Afinal em nenhuma hipotese seria util modelar algo com herança multipla… "
[/quote]
Escrevi errado:
Isso eh uma pergunta… esqueci o “?”
Não entendi ? A HM tem a função de reaproveitar codigo também pelo que eu saiba.
Voce poderia qualificar o super… que nem em python.
public void fazAlgo(int codigo){
ClasseMae.super.fazAlgo(codigo);
ClasseMaeAdotiva.super.fazAlgo(codigo);
}
dai tipo para manter a compatibilidade poderia ter a seguinte regra, se não tiver qualificado, então considera da primeira classe após a clausula extends…
O que vocÊ precisou fazer em Java e não conseguiu por falta de herança múltipla ?
Consegui eu consegui com interfaces só acho que em determinados casos seria mais facil fazer com HM.
Sim, mas não ao mesmo tempo a de modelar. A regra “É-UM” pode ser facilmente quebrada
Imagina class A extends B , Helper onde Helper tem um mote de codigo utilitário
A não é um Helper do ponto da modelagem, eu so estendi Helper para aproveitar o codigo.
Em java era comum usar constantes em interfaces e herdar as interfaces para ter acesso às constantes (SwingConstants, por exemplo).Isso é errado pelo mesmo motivo. A interface desempenhava o papel de utilitário de reaproveitamento de codigo sem respeitar a regra “É-UM”. Por isso vieram os Enum, e por isso este tipo de coisa é um anti-pattern. Portanto, HM não teria qualquer utilidade prática. Só criaria problemas e paradoxos.
Um das coisas que acho melhores no Java é a sua sintaxe simples e a sua politica de fazer muito com pouco. Herança simples é poderosa o suficiente, não precisa sequer existir um herança multipla. Claro, não precisa existir HM porque termos interfaces, entenda-se.
Sim, em alguns casos a HM seria útil, da mesma forma que citaram ai acima, que em alguns casos a HM permitiria que fossem feitas coisas que não deveriam ser feitas.
Eu acho que é questão de se adaptar ao que se tem disponível.
[quote=paulohrl ] Sim, mas não ao mesmo tempo a de modelar. A regra “É-UM” pode ser facilmente quebrada
Imagina class A extends B , Helper onde Helper tem um mote de codigo utilitário
A não é um Helper do ponto da modelagem, eu so estendi Helper para aproveitar o codigo.
[/quote]
Sim neste caso é gambi… mais na modelagem algumas vezes encontramos classes que tem esta caracteristica:
class Helicoptero extends Transporte, Ativo
Assim posso tanto me referir ao Helicoptero como um Transporte e um Ativo claro que isto é perfeitamente possivel com o uso de interface mas imagine que para cada veiculo que eu tivesse eu teria que implementar coisas referentes a interface Ativo
public interface Ativo
{
double getValor();
int getTempoDepreciacao();
}
public class Transporte
{
// Varios metodos.
}
public class Helicoptero extends Transporte implements Ativo
{
// Metodos proprios
private double valor;
private int tempoDepreciacao;
public double getValor(){
return valor;
}
public int getTempoDepreciacao(){
return tempoDepreciacao;
}
}
public class Yate extends Transporte implements Ativo
{
// Metodos proprios
private double valor;
private int tempoDepreciacao;
public double getValor(){
return valor;
}
public int getTempoDepreciacao(){
return tempoDepreciacao;
}
}
public class CarroParticular extends Transporte implements Ativo
{
// Metodos proprios
private double valor;
private int tempoDepreciacao;
public double getValor(){
return valor;
}
public int getTempoDepreciacao(){
return tempoDepreciacao;
}
}
para cada classe tive que criar um metodo getValor() e getTempoDepreciacao(), e criar duas variaveis de instancia.
Já com HM ficaria:
class Ativo
{
private double valor;
private int tempoDepreciacao;
public double getValor(){
return valor;
}
public int getTempoDepreciacao(){
return tempoDepreciacao;
}
}
class Transporte
{
// Varios metodos.
}
class Helicoptero extends Transporte, Ativo
{
// Metodos proprios
}
class Yate extends Transporte, Ativo
{
// Metodos proprios
}
class CarroParticular extends Transporte, Ativo
{
// Metodos proprios
}
O que é do Ativo fica na classe ativo. bem mais simples e não duplica código.
Concordo com você que facilitaria em alguns casos. O que estou dizendo é que é possível fazer qualquer coisa sem utilizar a HM.
Mais só porque é possivel não quer dizer que seja a melhor maneira. da pra fazer qualquer laço de repetição em pascal usando apenas if e goto mais nem por isso retiraram os fors e whiles.
Isso cai no que eu tinha falado, parece que a linguagem presume que o programador é idiota. e que para evitar dele cometer erros tiram recursos que possam ser uteis mas que consideram dificeis. 
Esse exemplo do ativo não é o melhor para demostrar a necessidade de HM porque começa com um erro de modelagem. Um Transporte não é um ativo (Violação do É-UM). Aliás , pode ser um Passivo :lol:
VC está querendo reaproveitar codigo…
O que eu quero dizer é que “Ativo” é um papel que Transporte desempenha num contexto (Contábil). Isso não é modelável com “É-UM” (É o mesmo problema de pessoa fisica e juridica) Teria que ser assim :
Transporte t = ...
Activo act = Activo.ativoPara(t);
Eu entendi o que vc quiz dizer, mas duvido que usar HM seja sinônimo de boa modelagem.
Em nenhum momento eu disse que Transporte é um ativo.
public class Transporte
{
}
Helicoptero, Carro e Yate são Ativos.
Em nenhum momento eu disse que Transporte é um ativo.
public class Transporte
{
}
Helicoptero, Carro e Yate são Ativos.[/quote]
Ok, mas o argumento se mantem. Só trocar “transporte” por qualquer um dos transportes reais.
Motivo de Java não ter herança múltipla é por causa do efeito Diamante que pode acontecer no Design.
AndrewAguiar mostrou um exemplo bastante interessante sobre herança múltipla. Mas eu poderia mostrar esse mesmo exemplo, sem utilizar herança múltipla e, ao mesmo tempo, sem replicação de código. Veja:
A interface Ativo e a classe Transporte seriam as mesmas.
public interface Ativo
{
double getValor();
int getTempoDepreciacao();
}
public class Transporte
{
// Varios metodos.
}
Agora eu teria a classe AtivoImpl, que implementa Ativo:
public class AtivoImpl implements Ativo
{
private double valor;
private int tempoDepreciacao;
public double getValor(){
return valor;
}
public int getTempoDepreciacao(){
return tempoDepreciacao;
}
}
E aí, as classes que herdam de Transporte (não todas) teriam uma instância de Ativo:
public class Helicoptero extends Transporte
{
// Metodos proprios
private Ativo ativo = new AtivoImpl();
public Ativo getAtivo(){
return ativo;
}
}
public class Yate extends Transporte
{
// Metodos proprios
private Ativo ativo = new AtivoImpl();
public Ativo getAtivo(){
return ativo;
}
}
public class CarroParticular extends Transporte
{
// Metodos proprios
private Ativo ativo = new AtivoImpl();
public Ativo getAtivo(){
return ativo;
}
}
E aí, sempre que o cliente precisar de saber algo do transporte como ativo, basta fazer:
CarroParticular cp = new CarroParticular();
// um monte de regras...
Ativo ativoCarroParticular = cp.getAtivo();
double valor = ativoCarroParticular.getValor();
Tudo bem, não é tão bonito se tivesse herança múltipla, mas ela resolve o problema de não se repetir código, ao mesmo tempo fazendo uso apenas de herança simples. E isso pode ser feito em qualquer situação onde a modelagem pede a herança múltipla, basta pegar o “elo mais fraco”, no nosso caso a inteface Ativo, e transformá-la em um relacionamento TEM-UM.