Existe polimorfismo sem herança

Existe polimorfismo sem herança.
:?:

Boa pergunta. Acho que sim, usando interfaces.

Não, não existe polimorfismo sem uma hierarquia. Existe herança seja usando “extend” ou “implements”.

Não… polimorfismo o que significa muitas formas é um conceito usado pelo “é um”…


 interface Face {
    public void doIt();
 }

 class A implements Face {
    public void doIt() {
      System.out.println("A");
    }    
 }

 class B implements Face {
    public void doIt() {
      System.out.println("B");
    }    
 }

 class Teste {
    public static void main(String args[]) {
      Face f = new A();
      Face f2 = new B();
      f.doIt();   //Saida A
      f2.doIt(); //Saida B
    }    
 }

Como pode ver temos a interface Face a qual poderia tbm ser uma classe o qual as outras subclasse as usassem… a interface Face tem o metodo doIt o qual é implementado/herdado pelas subclasses A e B porem este metodo tem uma “forma” em A e outra em B executando funções distintas nestas classes distintas…
tanto A como B passam no teste “é um” com Face…
bem grossamente isto é um conceito de polimorfismo…
porem lembre-se quem tanto uma classe concreta herdada como uma interface suas subclasses (classes que herdam/implementam elas) passam no teste “é um”… o conceito de herança não significa que tenha que ser com classes usando extends… vc pode usar interfaces como no meu exemplo… aliais é sempre melhor vc usar interfaces do que classes pais (classe que tera outras que vão herdar dela…) procure sempre evitar herança com “extends” prefira interfaces…

Boa pergunta, e se formos para ruby, duck typing pode ser considerado polimorfismo sem herança?

interfaces usam o conceito de herança… a diferença é que em uma interface todos os metodos nela que serão herdados pelas classes filhas devem ser obrigatoriamente implementados… ja com classes não abstratas com metodos não abstratos qdo estes metodos são herdados vc não precisa implementalos na classe que os herdou…

Hmm… então implementar uma interface também é considerado herança.

Ótima pergunta, o wikipedia responde:

Polimorfismo tem um contexto mais amplo. Embora tenha sido convencionado pela Sun não usar a terminologia assim para a linguagem Java, sobrecarga de métodos pode ser considerada polimorfismo:

[code]public class X() {
public void sayIt(int x) {
System.out.println("X is an integer of value: " + x);
}

public void sayIt(double x) {
      System.out.printf("X is a double of value: %.02d", x);
      System.out.println();
}

}[/code]

Note que existe comportamento polimórfico:

X x = new X(); x.sayIt(10); //X is an integer of value: 10 x.sayIt(12.5); //X is a double of value: 12.50

No C++, também existe polimorfismo em templates. E não envolve herança. Você pode fazer especialização da template para um determinado tipo. Um exemplo disso é que, no C++, o std::vector<boolean> tem uma implementação especial, usar 1 byte para representar 8 booleans. Note que não estamos falando de um filho de vector, mas do mesmo objeto numa determinada condição de uso.

Diferente dos Generics, no C++, os argumentos de template também tem comportamento polimórfico, pois fazem Duck Typing. Duck Typing implementa o conceito de “Se fala como um pato, e anda como um pato, então é um pato”. Demonstrando o conceito, veja o seguinte exemplo:

template<typename T> T max(T one, T two) { return one < two ? two : one; }

One or two podem ser qualquer objeto, ou tipo primitivo, desde que esse suporte o uso do operador <. Se os dois podem ser comparados com o sinal de menor, então essa função deve se comportar como tal. Esse também é um exemplo de polimorfismo sem herança, porque a resolução do tipo é dinâmica e depende apenas dos objetos terem ou não aquela “assinatura”. No caso do C++ é feita em tempo de compilação. Linguagens de script, como Groovy e Ruby, fazem em tempo de execução.

Interfaces tem muito menos acoplamento do que a herança.

Elas não dizem que X é um Y. Mas sim que X se comporta como um Y ou, em outras palavras, que X respeita o contrato de Y. Com interfaces, podemos variar a implementação livremente, o que não ocorre com a herança. Conceitualmente, também temos uma diferença. Bom, já houve uma longa discussão sobre isso nesse tópico:
http://www.guj.com.br/posts/list/51866.java#273117

sim são bem menos acoplados de herança porem utilizam o conceito “é um”… interface usa o conceito de herança… se vc olhar bem vai ver que a grosso modo uma interface nada mais é do que uma classe abstrata com todos os metodos declarados abstratos… a questão não são palavras reservadas como: extends e implements e sim o conceito do “é um”…

[quote=Danilo_neco]Existe polimorfismo sem herança.
:?:
[/quote]

Sim. com certeza. Repare que o polimorfismo que necessita de herança é apenas um tipo: o polimorfismo dinâmico.
O polimorfismo estático não depende de herança. Herança é uma forma de criar um escopo léxico suplementar, mas sem ele
ainda temos outros escopos em que o polimorfismo de aplica.

Mais detalhe aqui

Sergio estava olhando seu Wiki…

pq colocou Sobre-escrita como estatico?
sobre escrita é usado com herança… é impossivel vc fazer uma sobscrita na mesma classe…

[quote=luistiagos]Sergio estava olhando seu Wiki…

pq colocou Sobre-escrita como estatico?
sobre escrita é usado com herança… é impossivel vc fazer uma sobscrita na mesma classe…[/quote]

“sobescrita” não existe. É sobre-escrita (escrever por cima) :wink: Portanto sim, é impossivel fazer sobescrita na mesma classe :wink:
Agora a sério : sobre-escrita é estático porque vc pode encontrar o resultado real apenas lendo o código. Uma ferramenta que analize o codigo pode saber onde existe sobre-escrita; por isso é estático ( não precisa do runtime).

Polimorfismo não é relacionado a herança em geral. Apenas algumas coisas existem que são relacionadas a herança.
Mas herança é um conceito especial que aumenta os escopos disponiveis. Em outras linguagens sem herança (javacript por exemplo) o mesmo escopo pode ser definido e sobre-escrita poderia ser definida da mesma forma. Polimorfismo se relaciona a escopos. Herança é apenas uma forma de criar um deles.

bem mas vc esta falando de Runtime ou não e não de conceito… o fato de uma sobre - escrita poder ser vista em tempo de compilação não torna tal não sujeita a herança/implementação pois para se usar uma sobscrita vc obrigatoriamente tenque sobscrever o metodo herdado/implementado isto é aplicado ao conceito de herança… isto idepende de runtime… e var-args nada passa de um mode de vc passar um array de um determinado tipo com tamanho variavel… não entendo pq incluiu var-args nesta lista tbm…

Isso é porque vc confunde polimorfismo com herança e não entendeu a diferença entre polimorfismo estático e dinâmico.
Quando vc entender vc vai entender também porque inclui var args. Mas só para não dizerem que sou mau , pense que var args é uma forma especial de sobrecarga.

Ah! e é “sobre-escrita” ( ou sobre escrita) e não “sobescrita”

No seu “se você pensar bem”, você falou da implementação, não do conceito. Em linguagens com duck typing, por exemplo, o conceito de interfaces existe, mas não é necessário qualquer tipo de implementação ou declaração de uma interface formal. Basta a documentação. É o caso do C++ em metaprogramação, por exemplo.

Veja o exemplo que eu passei anteriormente, da função max.
Existe uma interface implícita para o tipo T, que seria algo assim:

interface de T { /** Retorna true se este T é menor que o outro. */ operator < (T outro); }

Mas não há uma classe abstrata ou interface formal definida na linguagem. Tudo será verificado na hora da compilação. No caso do Ruby, na hora da execução.

Agora, herança envolve um acoplamento muito mais forte. Como o Sergio falou, envolve a ampliação do escopo, compartilhamento de dados e de código. E as linguagens terão mecanismos formais para dizer que essa relação ocorreu.

Um usuário pode implementar uma interface, e com isso ele não está dizendo que a sua classe “é outra coisa”. Ele só diz que sua classe “está de acordo com determinado contrato”. É o que acontece quando vc implementa uma interface para se adequar com um framework, por exemplo. Em resumo, o tipo de dado original, não muda. Ele só se torna compatível com determinado método, que espera certas coisas serem cumpridas.

Por outro lado, um usuário não pode fazer herança, sem dizer que a classe dele mudou de tipo. A partir do momento que a herança ocorre ele tem uma nova entidade, que não é mais a mesma de antes da herança. É uma nova classe, mesmo.

É claro que a implementação disso tudo é muito parecida. Métodos como instanceof serão compatíveis com ambos. É conveniente e interessante.

Aliás, vários dos conceitos de OO podem ter implementação idêntica (por exemplo, muitos casos de Associação e Composição). O importante é entender como a relação entre as classes se dá, e não exatamente como elas estão representadas no código de uma determinada linguagem.

Eu não confundo polimorfismo com herança… acho que vc não leu meus outros posts ou se leu não entendeu bulhufas do que eu disse… em parte alguma disse que polimorfismo == herança são coisas destintas… eu posso ter polimorfismo atravez da herança… e posso telo atravez do overload…
templates tbm no C++ (havia me esquecido dos templates) porem var-args realmente não entendi onde vc quer encaixar… pode ser usado em overload sim como qualquer outro tipo… porem isto não o torna nada de especial…

Vini então pelo que vc esta dizendo se eu fizer isto:


abstract class A {
   public abstract void doIt();
}

class B extends A {
  public void doIt() {

  }
}

então se eu disser que B é um A estarei mentindo?

[quote=luistiagos][quote]
Isso é porque vc confunde polimorfismo com herança e não entendeu a diferença entre polimorfismo estático e dinâmico.
Quando vc entender vc vai entender também porque inclui var args. Mas só para não dizerem que sou mau , pense que var args é uma forma especial de sobrecarga.

Ah! e é “sobre-escrita” ( ou sobre escrita) e não “sobescrita”
[/quote]

Eu não confundo polimorfismo com herança… acho que vc não leu meus outros posts ou se leu não entendeu bulhufas do que eu disse… em parte alguma disse que polimorfismo == herança são coisas destintas… eu posso ter polimorfismo atravez da herança… e posso telo atravez do overload…
templates tbm no C++ (havia me esquecido dos templates) porem var-args realmente não entendi onde vc quer encaixar… um var arg não passa de um array… isto:


public void foo(int ...x) {

}

é exatamente igual a isto:


public void foo(int []x) {

}

a unica coisa que muda é a chamada do metodo sem var-args vc usa: foo(new int[]{1,2,3}) com var-args:
foo(1,2,3) porem um é igual ao outro… var-args é apenas um recurso da linguagem feito para simplificar a chamada do metodo não precisando criar um array para passar os argumentos porem isto é feito de qualquer modo mas implicitamente… dizer que var-args é uma especie de sobrecarga não é verdade pois:
foo(new int[]{1,2}) e foo(new int[]{1,2,3}) e foo(new int[]{1,2,3,4}) não são overloads e sim apenas um metodo que recebe um array de inteiros…

Vini então pelo que vc esta dizendo se eu fizer isto:


abstract class A {
   public abstract void doIt();
}

class B extends A {
  public void doIt() {

  }
}

então se eu disser que B é um A estarei mentindo?[/quote]

a diferença é que no var-args vc nao informa quantos paramentos devem ser passados no metodos, vc pode passar de 1 à …

e a respeito de herança e polimorfismo… pense assim, vc herda a herança do seu pai por seu filho. Ja o polimorfismo significa muitas formas… por exemplo todo animal corre ne? mais o gato de uma forma, o cachorro de outra, a galinha de outra entao ai vc tem polimorfismo. todo mundo na mesma cadeia… porem de forma diferente… em trazendo para “familia” sua irma é uma herança do seu pai tb, como vc… mais ela usa calcinha e vc usa cueca, porem ambos usa roupa intima!

flw! hehe!

eu tbm posso ter um array de 1 a … e passa-lo para o metodo veja meu exemplo acima…

para vc ver como eu não sou mentiroso tente compilar isto e veja o que vai dar:


class X {

   public void fazAlgo(int ...arr) {

   }

    public void fazAlgo(int []arr) {

   }

}

se var-args é um tipo especial de sobrecarga isto vai compilar e rodar perfeitamente…

e sobre heraça e polimorfismo ngn aqui disse em momento algum que herança == poliformfismo…
a questão era se existe polimorfismo sem herança… a unica maneira plausivel para isto em java é a sobrecarga… de fato em minha primeira resposta a este post esqueci da sobrecarga que usa o conceito de polimorfismo…