Por que o Java não permite o uso de cabeçalhos como em C ++

18

Tenho uma pergunta para a qual não encontrei uma resposta, exceto a seguinte resposta que não atende aos meus requisitos:

"Porque James Gosling não queria"

Eu sei que o Java pode ter interfaces (apenas funções virtuais puras, sem atributos), mas não é exatamente a mesma coisa que as definições de classe.

Etienne Noël
fonte
14
Qual é a razão pela qual você os quer?
19
Para ter mais tempo para swordfights;)
dan04
6
Suponho que a maioria dos desenvolvedores de C ++ adoraria se livrar do mecanismo de substituição de texto de 40 anos que duplica centenas de kLoC para cada arquivo cpp, levando a longos tempos de compilação do C ++. De fato, um sistema de módulos adequado foi contemplado para o C ++ 11, mas caiu devido à falta de tempo. Suponho que voltará a aparecer, no entanto.
S11/
Suponho que voltará a aparecer, no entanto. De fato, o WG21 (grupo de trabalho ISO C ++) possui um grupo de estudo apenas com o objetivo de avaliar / desenvolver ainda mais o conceito de "módulos": SG2 "Módulos". Pena que o status atual esteja inativo .
Max Truxa

Respostas:

46

A resposta a seguir não atende aos meus requisitos: "Porque James Gosling não queria".

Essa é a resposta certa, no entanto. A equipe de design de idiomas (Gosling, Sheridan, Naughton, mais tarde Bill Joy, Ken Arnold etc.) decidiu que os cabeçalhos causavam mais problemas do que resolviam . Então eles os projetaram e demonstraram que poderiam criar uma linguagem perfeitamente útil sem a necessidade deles.

Da seção 2.2.1 do white paper Java Language Environment :

O código-fonte escrito em Java é simples. Não há pré-processador, nem #define e recursos relacionados, nem typedef, e ausente esses recursos, não há mais necessidade de arquivos de cabeçalho. Em vez de arquivos de cabeçalho, os arquivos de origem da linguagem Java fornecem as definições de outras classes e seus métodos.

Definições redundantes, mantendo arquivos sincronizados, definições conflitantes, definições ocultas - nada disso ocorre em Java, porque você não possui cabeçalhos. Se você deseja ver uma definição de classe simples, pode gerá-la diretamente de um arquivo .java - por exemplo, a maioria dos IDEs mostrará a estrutura de uma classe em uma barra lateral, o que equivale à mesma coisa.

Alex Feinman
fonte
6
Obrigado pela sua resposta, então, os cabeçalhos causaram mais problemas por causa disso: Definições redundantes, mantendo arquivos sincronizados, definições conflitantes, definições ocultas. É por isso que não foi permitido?
Etienne Noël
2
Observe que há muitas conversas sobre as próximas reuniões do C ++ Commitee porque elas consideram um novo sistema de "Módulo" que seria um sistema mais simples e eficiente do que incluir (com algumas semelhanças com pacotes java, C # etc.), mas ainda retro -compatível com inclui. Isso significa que um sistema de compilação melhor pode, pelo menos em teoria, ser usado para tornar a compilação de C ++ melhor / mais eficiente. Acho que Gosling estava certo, e o C ++ precisa encontrar uma maneira de corrigir o sistema de inclusão.
Klaim
5
Não é perfeitamente utilizável. Os sistemas de construção Java não conseguem determinar quais arquivos devem ser recompilados após uma alteração no código. Um IDE determinará quais arquivos requerem uma alteração de código, mas não quais precisam de recompilação. Se uma assinatura de método for alterada, mas a alteração for compatível com o código da assinatura antiga (por exemplo, alterar um tipo de argumento de float para double), será necessária uma compilação limpa para evitar MethodNotFoundException.
Novidade
1
@ Kevin: No entanto, geralmente é possível reconstruir tudo sem muito custo. Ao contrário do C ++ (mas como quase todas as outras linguagens compiladas do mundo), o Java não leva muito tempo para compilar que a compilação parcial é uma otimização muito interessante do seu fluxo de trabalho de desenvolvimento.
Donal Fellows
1
@Donal: É verdade que o Java compila muito rapidamente, mas eu odeio adivinhar se devo ou não fazer uma recompilação completa. Builds devem funcionar sempre .
kevin Cline
16

Não há necessidade real no C ++ de ter as definições e declarações de classe em arquivos separados. Significa apenas que você poderia, pelo menos nos dias C, fazer a análise em uma única varredura na parte superior e inferior do código. Em máquinas sem armazenamento de acesso aleatório, isso era muito importante!

Ter cabeçalhos também permitiu publicar a interface na sua biblioteca de códigos fornecendo o cabeçalho sem a necessidade de revelar o código-fonte. Infelizmente, em C ++, você também precisa revelar os membros de dados privados, o que levou a soluções como o horror do pimpl .

Houve tentativas de criar um ambiente C ++ em que tudo era armazenado em uma estrutura de tipo de banco de dados e não havia arquivos, mas ele não entendeu.

Martin Beckett
fonte
Eu sei disso, mas pelo menos você pode fazê-lo em C ++ e não em Java; essa foi minha pergunta principal. Obrigado pela resposta.
Etienne Noël
14

Por causa do princípio DRY . Em Java, as informações necessárias para usar classes em um pacote (ou classe) estão contidas no arquivo .class. Criar arquivos de cabeçalho separados que contenham as mesmas informações envolveria a repetição em dois lugares.

Jay Elston
fonte
infelizmente, muitas vezes você deseja repeti-lo - pense nos arquivos wsdl, idl etc. Um descreve a interface que você pode usar e outro arquivo contém a implementação. Cabeçalhos C ++ são definições de interface (ruins).
precisa saber é o seguinte
6

Em todos os idiomas - há dois estágios para a criação do código binário final - compilação e vinculação (é claro, há carregamento, mas isso não tem muito impacto aqui). No momento da compilação, é necessário colocar os ganchos (a especificação das funções que serão chamadas) no local apropriado. O Linker realmente os une quando o código real está disponível. Até o momento, não há diferença entre C ++ e Java.

Não é , no entanto, a necessidade de C ++ para ter declaração e definição separada. Se você mantiver a implementação no cabeçalho e se o arquivo do cabeçalho for alterado, o código vinculado a ele precisará ser recompilado. Onde como se a definição estivesse em um arquivo separado, o código só precisa ser vinculado novamente.

Entenda que o C ++ tem a opção de ter vínculo estático, o que implica que o código do objeto seja corrigido junto com o aplicativo de chamada. Observe que, tanto em C como em C ++, não é inválido ter programação no arquivo de cabeçalho ou até mesmo #include. isso significa apenas que você precisa se preocupar sobre como a vinculação acontece com esses arquivos de objeto.

A situação em Java é muito diferente. Cada arquivo de classe é compilado com o arquivo .class. De fato, a necessidade de compilação de funções de classe de chamador, que é servida como uma seção de cabeçalho no arquivo .class. No entanto, no Java, a vinculação final é feita apenas dentro do Runtime (a máquina virtual) apenas com essa especificação do código de bytes do arquivo de classe.

Veja isso e isso

Dipan Mehta
fonte
4

Efetivamente, as interfaces e inclusões são os cabeçalhos; as definições são, portanto, idênticas aos binários e não podem estar fora de sincronia. Essa é uma das melhores decisões de design em Java, mas é um incômodo menor que não haja maneira de agrupar essas declarações para compacidade e consistência.

ddyer
fonte
1

Um bom motivo para incluir é separar o código que você deseja reutilizar (como definições comuns) do código específico para um determinado projeto. Java quer que você especifique apenas uma classe ou interface por arquivo e isso reduz a necessidade de cabeçalhos incluídos - pois você terá as partes compartilhadas já em seus próprios arquivos.

Além disso, os compiladores e os sistemas de compilação podem querer armazenar em cache os cabeçalhos pré-compilados para evitar a análise mais de uma vez.

rbanffy
fonte
1
Suponho que você possa armazenar as interfaces em um projeto compartilhado e depois implementá-las em projetos independentes.
Alexander Mills