HERANÇA MULTIPLA vs JAVA

[quote=“mmpaulo”]hilmilho
no caso de métodos conflitantes, poderia ser usada a assinatura dos métodos para fazer a diferenciação(como quando vc define métodos com o mesmo nome e assinaturas diferentes em uma mesma classe, por exemplo)… [/quote]

Provavelmente os métodos representam o mesmo comportamento. Diferenciá-los, como você disse nas entrelinhas, não seria possível em métodos sem parâmetros. Para métodos com um parâmetro, seria possível acresentar outro para diferenciar. Um desavisado poderia tentar remover esse parâmetro aparentemente inútil. Outra opção, em assinaturas com dois ou mais parâmetros, mudar a ordem dos mesmos. Talvez mudar o tipo de um parâmetro também ajude. Mas se acrescentarmos ali, além de Dinossauro e Sapo, mais alguns tipos de animais, essa diferenciação por assinatura vai ficando inviável. Acho que nisso o Java mandou bem.

dinossauro = (Dinossauro) sapossauro;
dinossauro.falar()

Aí seria preciso “jogar fora” a parte Sapo do objeto sendo ‘casteado’. me parece que em C++ é possível acessar o endereço de uma das classes componentes da herança múltipla. Interessante:

[quote]class A {…};
class B : public A {…};
class C : public A {…};
class D : public B, public C {…};

If you create an object of class D, that object may have up to five
different addresses, depending upon how its used:

D d; // create object of class D

D* p1 = &d; // p1 is address of D part of d

B* p2 = &d; // p2 is address of B part of d

C* p3 = &d; // p3 is address of C part of d

A* p4 = (B*) &d; // p4 is address of A part of B part of d

A* p5 = (C*) &d; // p5 is address of A part of C part of d[/quote]
http://cpptips.hyperformix.com/cpptips/diff_address

[quote]dinossauro = (Dinossauro) sapossauro;
dinossauro.falar()
Aí seria preciso “jogar fora” a parte Sapo do objeto sendo ‘casteado’.[/quote]
nao… eu disse um cast especial… algo que serve apenas para a maquina virtual saber qual método estamos usando

[code]
public class A {
public void x() {
System.out.println(“Método x da classe A”);
}
}

public class B {
public void x() {
System.out.println(“Método x da classe B”);
}
}

public class C extends A, B {

}


public void metodoQualquer() {
C obj = new C();
obj.x();
}

/* Não compila, o compilador nao sabe se deve chamar o método x da classe A ou da classe B */

public void metodoQualquer() {
C obj = new C();
[A]obj.x(); /* Imprime “Método x da classe A” /
}
/
Aqui vc não transforma um objeto da classe C(A, B) em um objeto da classe A, desprezando a sua porção da classe B, mas instrui o compilador dizendo 'compilador, eu sei que existem dois métodos iguais nas minhas superclasses, mas eu estou explicitando que quero usar o método da classe A, sacou? */

mas reconheço q isso iria complicar muito se acontecesse algo assim, por exemplo:
uma classe A q implementa o método x()
uma classe B q implementa o método x()
uma classe C q estende A e B
uma classe D q implementa o método x()
uma classe E q estende C e D
a minha classe E tem 3 metodos x(), vai ficar complicado usar a sintaxe q eu sugeri para especificar qual método queremos usar… até é possivel, mas fica mto feio, ainda mais se houvessem mais classes implementando o método x().

outra abordagem, é simplesmente nao compilar, uai…
com o uso de interfaces, pode ocorrer um conflito de métodos e o programa simplesmente não compila, pq com classes nao poderia ser igual?
[code]
interface InterfaceA {
public void x();
}

interface InterfaceB {
public int x();
}

public class MinhaClasse implements InterfaceA, InterfaceB {
/* Iae, como implementar o método x()?
Se eu tentar escolher apenas um, ou o da InterfaceA ou o da InterfaceB, o programa nao compila… se eu implementar os dois, tb não compila, pq vai ter dois métodos iguais, mudando apenas o tipo de retorno, e isso não basta para o compilador saber qual vc estará querendo usar em determinado momento… */
}[/code]

[quote=“mmpaulo”]public void metodoQualquer() {
C obj = new C();
[A]obj.x(); /* Imprime “Método x da classe A” /
}
/
Aqui vc não transforma um objeto da classe C(A, B) em um objeto da classe A, desprezando a sua porção da classe B, mas instrui o compilador dizendo 'compilador, eu sei que existem dois métodos iguais nas minhas superclasses, mas eu estou explicitando que quero usar o método da classe A, sacou? */[/quote]

Ok, realmente poderia ficar complicado. Aquele último código em c++ ele cria ponteiros pra “partes” da classe. Mas desse jeito aí é mais intuitivo.

[quote=“mmpaulo”]outra abordagem, é simplesmente nao compilar, uai…
com o uso de interfaces, pode ocorrer um conflito de métodos e o programa simplesmente compila, pq com classes nao poderia ser igual?

[code]
interface InterfaceA {
public void x();
}

interface InterfaceB {
public int x();
}

public class MinhaClasse implements InterfaceA, InterfaceB {
/* Iae, como implementar o método x()?
Se eu tentar escolher apenas um, ou o da InterfaceA ou o da InterfaceB, o programa nao compila… se eu implementar os dois, tb não compila, pq vai ter dois métodos iguais, mudando apenas o tipo de retorno, e isso não basta para o compilador saber qual vc estará querendo usar em determinado momento… */
}[/code][/quote]

Interessante esse exemplo!
Realmente impossível implementar o método x porque na verdade trata-se de um único método(mesma assinatura).
Um método só pode ter um tipo de retorno.
Se não desse erro seria como declarar

public void int x();

Em C++ quando uma classe herda de outras duas que possuem o mesmo método ela utiliza o método da classe que estiver declarada primeiro.

um problema clássico de interfaces:

[code]interface A {
void teste();
}

interface B {
int teste();
}

class C implements A,B {
// Como resolver a implementacao dos Metodos A#teste() e B#teste() ???
}[/code]
Nem sempre a interface resolve … neste caso eu não poderia implementar as duas.

Esse erro é bem clássico mesmo.

Isso implica que na hora de construirmos nossas interfaces, devemos prestar muita atenção no nome dos métodos. É claro que um projeto bem definido impediria esse erro. Mas supondo que tenha passado despercebido este erro, para resolver basta retirar a parte que implementa a interface B e mudar o nome do método no código da classe.

Pronto. Lembrando que uma interface é apenas um ferramente para melhorar a clareza e facilitar a documentação do código, porém não se faz necessária de forma nenhuma, podendo ser retirada sem maiores transtornos.

[quote=“Heber”]
um problema clássico de interfaces:

[code]interface A {
void teste();
}

interface B {
int teste();
}

class C implements A,B {
// Como resolver a implementacao dos Metodos A#teste() e B#teste() ???
}[/code]
Nem sempre a interface resolve … neste caso eu não poderia implementar as duas.[/quote]

Heber, esse exemplo é o que mmpaulo deu também.

Veja só, A#teste() e B#teste() têem a mesma assinatura(nome do método, tipo e quantidade de parâmetros). Quando vocêm implementa as duas interfaces, a classe recebe os métodos das duas interfaces.
Só que quando o compilador vai montar esse método sai algo como:
void int teste()
Como um método só pode ter um tipo de retorno, dá erro. Mas sou da opinião que o erro é do programador.

O meu objetivo com esse exemplo foi mostrar que utilizando interface não da pra resolver todas as lacunas deixadas pela falta de herança múltipla.

[quote=“feliperod”]Esse erro é bem clássico mesmo.

Isso implica que na hora de construirmos nossas interfaces, devemos prestar muita atenção no nome dos métodos. É claro que um projeto bem definido impediria esse erro. Mas supondo que tenha passado despercebido este erro, para resolver basta retirar a parte que implementa a interface B e mudar o nome do método no código da classe.

Pronto. Lembrando que uma interface é apenas um ferramente para melhorar a clareza e facilitar a documentação do código, porém não se faz necessária de forma nenhuma, podendo ser retirada sem maiores transtornos.[/quote]
discordo, cara…
tudo bem q pode-se tirar as interfaces e a gente se virar sem elas…
mas ‘sem maiores transtornos’ já é exagero…
só um exemplo: tenta imaginar o tratamento de eventos de uma interface grafica sem interfaces! tudo bem q ainda seria possivel trabalhar com os eventos, mas seria muito mais trabalhoso e ‘feio’

[quote=“mmpaulo”][quote=“feliperod”]Esse erro é bem clássico mesmo.

Isso implica que na hora de construirmos nossas interfaces, devemos prestar muita atenção no nome dos métodos. É claro que um projeto bem definido impediria esse erro. Mas supondo que tenha passado despercebido este erro, para resolver basta retirar a parte que implementa a interface B e mudar o nome do método no código da classe.

Pronto. Lembrando que uma interface é apenas um ferramente para melhorar a clareza e facilitar a documentação do código, porém não se faz necessária de forma nenhuma, podendo ser retirada sem maiores transtornos.[/quote]
discordo, cara…
tudo bem q pode-se tirar as interfaces e a gente se virar sem elas…
mas ‘sem maiores transtornos’ já é exagero…
só um exemplo: tenta imaginar o tratamento de eventos de uma interface grafica sem interfaces! tudo bem q ainda seria possivel trabalhar com os eventos, mas seria muito mais trabalhoso e ‘feio’[/quote]

Feio eu posso até concordar, só que mais trabalhoso??? O trabalho seria o mesmo, mas o conhecimento do programador teria que ser maior.

Aliás, para tratar eventos seria até melhor, afinal de contas no caso do MouseListener não seria necessário fazer overriding de todos os métodos da interface (são 4 métodos, se me lembro bem), apenas escreveria o que vai ser usado.

Portanto trabalhoso, não. Seria mais limpo o código.

No entanto, minha intenção não foi desestimular o uso de interfaces, e sim apresentar uma solução para o problema proposto, caso dois métodos fosse iguais em duas interfaces diferentes, retira-se uma delas e deixa a outra. Simples né…

Mas as interfaces para tratamentos de eventos só são interessantes pq já vem no JDK, caso contrário seria um transtorno. Já pensou, ter que criar todas as interfaces de tratamentos de eventos? Seria mais fácil copiar o código.

[quote=“feliperod”]Aliás, para tratar eventos seria até melhor, afinal de contas no caso do MouseListener não seria necessário fazer overriding de todos os métodos da interface (são 4 métodos, se me lembro bem), apenas escreveria o que vai ser usado.
[/quote]
eita
já ouviu falar nos adaptadores??

[quote=“feliperod”]
Mas as interfaces para tratamentos de eventos só são interessantes pq já vem no JDK, caso contrário seria um transtorno. Já pensou, ter que criar todas as interfaces de tratamentos de eventos? Seria mais fácil copiar o código.[/quote]
de qualquer forma, ou vc cria interfaces só para tratamento de eventos, ou cria classes para isso. como nao existe herança multipla, vai de interface mesmo.
se não, vc poderia incluir qualquer objeto como um actionlistener de um jbutton(exemplo), mesmo que esse objeto não seja um listener válido, nao implemente o método actionPerfoemed(), oque iria dar um certo pau na hora que um actionEvent ocorresse nesse botão

A Interface é tão importante quanto herança múltipla. Se não tivesse a Interface então teria que ter herança multipla para resolver milhares de problemas que iriam aparecer. Mas como foi adicionada as Interfaces então eles (SUN) não quiseram ter trabalho com a herança múltipla, visto que a implementação da JVM seria bem mais complicadas, assim como um monte de programadores que fazem “tudo no main” iriam querer utilizar a herança múltipla de forma errada não iam conseguir nem compilar o código e iriam desistir … Isso tornaria o Java bem menos popular, o que não é muito interessante.

Acredito que deveria existir herança multipla de classes por causa dos conceitos de OO.
E se alguém vem com o argumento: “Herança múltipla é muito falado mas ninguém em C++” ou “Nunca vi um programa em C++ utilizando herança multipla”.
Eu digo apenas o seguinte: “Como posso utilizar uma solução(função) que não está disponível?”

.

Quem precisa de heranca múltipla quando se pode escrever métodos sobrecarregados?! :razz:

Acho que ao garantir o polimorfismo de funcões e a possibilidade de se implementar múltiplas interfaces, o Java oferece uma solucão muito mais fácil para problemas que envolvem especializacão de classes.

Eu já vi heranca múltipla em Object Pascal e posso assegurar que não havia controle nenhum sobre as funcões que realmente se queriam implementar, ainda mais quando elas tinham o mesmo nome! :???:

Com isso, considero o recurso de interfaces uma grande sacada da SUN e que descarta qualquer solucão com heranca múltipla, embora despreze alguns conceitos da OO. Mas isso não é problema visto que a UML oferece todo suporte à representacão de classes que implementam interfaces. :grin:

mmpaulo escreveu:

[quote]de qualquer forma, ou vc cria interfaces só para tratamento de eventos, ou cria classes para isso. como nao existe herança multipla, vai de interface mesmo.
se não, vc poderia incluir qualquer objeto como um actionlistener de um jbutton(exemplo), mesmo que esse objeto não seja um listener válido, nao implemente o método actionPerfoemed(), oque iria dar um certo pau na hora que um actionEvent ocorresse nesse botão[/quote]

Bem, agora vc chegou no ponto que eu queria. Foi exatamente o que eu disse, a diferença seria apenas que o programador teria que ter um conhecimento muito maior para manipular eventos. Isso daria mais mobilidade (o que é possível em alguns casos). O método actionPerformed() poderia ter um nome qualquer. Mas aí rola uma dúvida.

Qual a relação dos “escutadores” com as interfaces?

addMouseLister(this);

Isso ficaria normal?

como assim, qq nome?
o actionPerformed() tem q continuar se chamando actionPerformed(), para que o JButton(exemplo) saiba quel método chamar nos objetos q foram registrados como seus action listeners, quando ocorrer um action event.
É justamente pra isso que teria q ser usado interface ou classe para implementar os listeners de um determinado tipo de evento, pra padronização(se não seria inviavel o tratamento de eventos como é feito atualmente no swing, swt, …)

seria sintaticamente correto… mas seria mto inutil hehe
tipo assim:

public class ManiPuladorDeEvento extends ActionListener {
public ManipuladorDeEvento(JButton b) {
b.addActionListener(this);
}
public void actionPerformed(ActionEvent ae) {

}
}
a classe seria só isso…
se for pra fazer assim, entao é mais facil fazer logo:
JButton b = new JButton("…");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {

}
});

[quote] justamente pra isso que teria q ser usado interface ou classe para implementar os listeners de um determinado tipo de evento, pra padronização(se não seria inviavel o tratamento de eventos como é feito atualmente no swing, swt, …)
[/quote]

Exatamente. Padronização. Essa é a principal função das interfaces.

Já imaginou um programador Java ter que desvendar quais métodos foram usados para tratar um evento em um aplicativo feito por outro programador? Nisso eu aplaudo as interfaces.

[quote]seria sintaticamente correto… mas seria mto inutil hehe
tipo assim:

public class ManiPuladorDeEvento extends ActionListener {
public ManipuladorDeEvento(JButton b) {
b.addActionListener(this);
}
public void actionPerformed(ActionEvent ae) {

}
}
a classe seria só isso…
se for pra fazer assim, entao é mais facil fazer logo:
JButton b = new JButton("…");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {

}
});[/quote]

Não deu na mesma? as duas formas não estão corretas?
Mas e se eu tentar criar um método para manipular um determinado evento, sem ter que implementar um interface? Seria possivel?

algo como:

[code]
public class ManipuladorDeEvento{

public void apertarBotao(String nome_botao) {
nome_botao= botao.label; //seria assim mesmo??? botao.label ???
System.out.print("vc apertou: "+nome_botao);
}
}[/code]

A dúvida é: Como fazer pro java saber que apertei o botão??? E como dizer pro java que quando eu apertar o botão é pra executar esse método. Se isso for possível, então seria uma alternativa ao uso de interfaces. Lembrando que não sou contra o uso de interfaces, pelo contrário, sou muito a favor. Mas para fins de aprendizado vamos prolongar o assunto.

acho que nao dá pra fazer isso nao, cara.
talvez eu esteja errado, maaas:
o jbutton foi projetado para receber apenas objetos ActionListener(isso inclui classes que implemenem essa interface, ou que estendessem a classe ActionListener[isso no caso q foi comentado aqui… caso nao existissem interfaces]), e ao ocorrer um action event, chamar o método actionPerformed dos seus listeners.

É… acho que eu estou querendo uma flexibilidade impossível. Aliás, aí seria uma bagunça só. Cada programa teria um cara diferente.

Na verdade isso é um forma de mostrar a importância das interfaces. Pelo menos no fonte do java. Agora, em projetos novos, acho que são pouco usadas.

Alguém usa interfaces com freqüência?
Em todos o programas?
E pra Web, alguém usa?

Só pra constar.

PS. - Vou tentar achar um jeito de tratar eventos sem usar interfaces. Se alguém quiser ajudar seria uma ótima maneira de aprender os fundamentos do java. Qualquer novidade postem aqui.

[quote=“feliperod”]Alguém usa interfaces com freqüência?
Em todos o programas?
E pra Web, alguém usa?
[/quote]
vira e meche eu uso, cara…

As primeiras classes que eu implemento em um projeto são as interfaces.

Eu uso direto, sem exceções … pra quem já jogou algum dos meus jogos (MoveBlocks ou PontoAPonto) e viu os códigos, percebeu a quantidade de interfaces que eu tenho não só para eventos mas também para classes de negócios.

[quote=“feliperod”]
PS. - Vou tentar achar um jeito de tratar eventos sem usar interfaces. Se alguém quiser ajudar seria uma ótima maneira de aprender os fundamentos do java. Qualquer novidade postem aqui.[/quote]
Utilizar interface é utilizar os fundamentos do Java e de OO. A interface deixa seu código mais elegante e menos Gambiarrático (ou Macarrônico).