Pergunta

Primeiro, eu sei quase nada sobre teoria da linguagem, e eu mal conheço qualquer outra língua, exceto Java, mas eu tive uma idéia que eu acho que seria legal, mas eu preciso que vocês me dizem:
A: Por que suga
b: como a linguagem x teve que durante anos
c: como minha mente suga
d: todos os itens acima

A idéia daria composição a mesma facilidade de reutilização de código que extends faz.

Então, se você teve uma classe como este:

public interface A {  
    public void methodInA();  
}

E então você teve uma classe como este:

public class B {  
    private composed A;
    public B() {
        // construct A within constructor
    }
}

Você, então, ser capaz de fazer isso:

B myB = new B();
myB.methodInA();

Sem ter que adicionar na delegação na classe de B. Mas você também pode fazer o mesmo que com a herança, ou seja:

@Overrides
public void methodInA(){
    // B's own delegation method
}

As desvantagens incluem:

  • métodos estão escondidos no código fonte, tornando-se menos óbvia onde a chamada está vindo, mas este é também o caso com extends
  • se os campos compostos partilham a mesma assinatura de método não precisa ser um conflito resolvido (como as interfaces conflitantes resolver isso?)
  • Se você queria ter vários campos compostas do mesmo tipo, haveria um evidente conflito para o qual campo delegar
  • provavelmente 100 outras coisas que eu não pensava

Como eu disse, eu sou, obviamente, nenhum teórico da linguagem, e eu não ter passado as idades pensando nisso, a idéia simplesmente apareceu na minha cabeça e eu queria saber o quão errado eu sou. Eu só acho que seria bem legal.

Foi útil?

Solução

Eu acho que se você restringiu-lo de tal forma que uma classe só pode usar esse recurso para compor uma única classe seria pouco útil e evitaria muitas das dores de cabeça que estão sendo discutidos.

Pessoalmente eu odeio herança de classes concretas. Eu sou um grande defensor do ponto 14 da Bloch do Effective Java , composição favor sobre inheritence . Eu acho que algo como isso iria torná-lo um pouco mais fácil para implementar o idioma ele recomenda nesse item.

Honestamente, se você realmente sabia o que estava fazendo Eu aposto que você poderia escrever uma anotação de compilador que iria lidar com isso. Assim, supondo que você teve uma classe Bar que implementou a interface IBar, sua classe ficaria assim:

public class Foo {

  @Delegate(IBar.class)
  private Bar bar;

  // initialize bar via constructor or setter
}

Em seguida, durante a compilação Foo poderia ser feito para implementar IBar e qualquer um dos métodos nessa interface que não foram já implementados por Foo acabaria sendo gerado para olhar como esta:

public Baz method1(Qux val) {
  return bar.method1(val);
}

Como mencionado acima, você gostaria de fazer a restrição de que apenas um campo por classe poderia usar essa anotação. Se vários campos teve essa anotação que você provavelmente gostaria de lançar um erro de compilação. Alternativamente, você pode descobrir uma maneira de codificar uma espécie de modelo de precedência para os parâmetros passados ??a ele.

Agora que eu escrevi isso que parece arrefecer meio. Talvez eu vou brincar com ele na próxima semana. Vou atualizar este se eu conseguir descobrir nada.

Outras dicas

Parece legal, mas eu acho que faz para algumas construções de linguagem horríveis. Obviamente há um problema se você declarar mais de uma 'composição' da mesma classe, mas mesmo se você não permita que o que acontece com o caso em que uma chamada corresponde a um método em mais de uma das (diferentes) classes compostas? Você teria que especificar qual era chamado na classe principal, e você precisaria de sintaxe extra para isso. A situação se torna ainda pior se há membros públicos nas classes.

A composição é utilizada para evitar problemas com a herança múltipla. Permitindo composição como este é permitir de forma eficaz a herança múltipla, pelo menos em termos de resolução de qual o método a chamar. Desde uma decisão importante projeto com Java foi para não permitir herança múltipla (por boas razões) Acho improvável que isso nunca iria ser introduzida para Java.

Eu não tenho certeza que eu vejo uma clara vantagem de fazer isso embora. Eu entendo o ponto que você está fazendo. No momento de chamar um método em um você tem que myB.getAInstance (). MethodInA (), mas você quer fazer essa myB.methodInA ().

Mas, o que acontece se você tiver várias instâncias de A? Como é que a chamada do método ser resolvido? Muitas vezes composição implica um para muitos associação de modo B tem muitos casos a. O que acontece então?

Eu concordo com seus inconvenientes listados. Pode simplesmente causar muita confusão do que vale a pena.

Confira o que é chamado de "Mixins" em algumas línguas, e "Funções" no sistema Perl 5 Moose OO.

Há também a diferença entre o composição e agregação a considerar. Como é que o know compilador se você quer dizer 'é-um' ou 'tem-um' relacionamentos?

  • Será que todo o gráfico do objeto se tornar elegível para coleta de lixo ou apenas a cabeça do gráfico?

Um par das ferramentas de mapeamento ORM e quadros sobre / em torno deles prever belongsTo ou has-many relações entre objetos persistentes e alguns também prevêem a exclusão em cascata (para composição). Eu não sei de um fora de mão que fornece o açúcar sintático simples que você está procurando.

Na verdade, pensando bem, metaclasse do Groovy e Metaprogramação idioma (s) pode fornecer algo muito semelhante, com a delegação 'auto-magic'.

A herança múltipla é permitido em C ++, eu sei que diferente, mas é ao longo do mesmo processo de pensamento. Java foi projetado para não permitir que a herança múltipla de modo que haveria menos confusão, portanto, erros e exploits.

O que você sugeriu está em conflito direto com os princípios de java.

Dito isto, seria legal (não necessariamente útil). Eu sou um programador java que mudaram de C ++. Eu gosto de ser capaz de fazer meus próprios erros.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top