¿Por qué Java no permite el uso de encabezados como en C ++?

18

Tengo una pregunta para la que no encontré una respuesta, excepto la siguiente respuesta que no cumple con mis requisitos:

"Porque James Gosling no quería"

Sé que Java puede tener interfaces (solo funciones virtuales puras, sin atributos), pero no es exactamente lo mismo que las definiciones de clase.

Etienne Noël
fuente
14
¿Cuál es la razón por la que los quieres?
19
Para tener más tiempo para las peleas de espadas;)
dan04
66
Supongo que a la mayoría de los desarrolladores de C ++ les encantaría deshacerse del motor de reemplazo de texto de 40 años que duplica cientos de kLoC por cada archivo cpp, lo que lleva a largos tiempos de compilación de C ++. De hecho, se consideró un sistema de módulos adecuado para C ++ 11, pero se cayó debido a la falta de tiempo. Sin embargo, supongo que volverá a aparecer.
sbi
Sin embargo, supongo que volverá a aparecer. De hecho, WG21 (el grupo de trabajo ISO C ++) tiene un grupo de estudio con el único fin de evaluar / desarrollar el concepto de "módulos": los "Módulos" SG2. Lástima que su estado actual esté inactivo .
Max Truxa

Respuestas:

46

La siguiente respuesta que no cumple con mis requisitos: "Porque James Gosling no quería".

Sin embargo, esa es la respuesta correcta. El equipo de diseño del lenguaje (Gosling, Sheridan, Naughton, luego Bill Joy, Ken Arnold, etc.) decidió que los encabezados causaron más problemas de los que resolvieron . Entonces los diseñaron y demostraron que podían crear un lenguaje perfectamente útil sin la necesidad de ellos.

Desde la Sección 2.2.1 del libro blanco del lenguaje Java Medio Ambiente :

El código fuente escrito en Java es simple. No hay un preprocesador, no #define y capacidades relacionadas, no typedef, y en ausencia de esas características, ya no hay necesidad de archivos de encabezado. En lugar de archivos de encabezado, los archivos fuente del lenguaje Java proporcionan las definiciones de otras clases y sus métodos.

Definiciones redundantes, mantener archivos sincronizados, definiciones conflictivas, definiciones ocultas, ninguna de estas ocurre en Java, porque no tiene encabezados. Si desea ver una definición de clase básica, puede generarla directamente desde un archivo .java; por ejemplo, la mayoría de los IDE le mostrarán la estructura de una clase en una barra lateral, lo que equivale a lo mismo.

Alex Feinman
fuente
66
Gracias por su respuesta, los encabezados causaron más problemas debido a eso: definiciones redundantes, mantener archivos sincronizados, definiciones conflictivas, definiciones ocultas. ¿Es por eso que no estaba permitido?
Etienne Noël
2
Tenga en cuenta que se habla mucho sobre las próximas reuniones del Comité de C ++ porque considerarán un nuevo sistema "Módulo" que sería un sistema más simple y más eficiente que incluir (con algunas similitudes con los paquetes de Java, C # etc.) pero aún retro -compatible con incluye. Es decir que un mejor sistema de compilación puede, al menos en teoría, usarse para hacer que la compilación de C ++ sea mejor / más eficiente. Gosling tenía razón, supongo, y C ++ tiene que encontrar una manera de arreglar el sistema de inclusión de todos modos.
Klaim
55
No es perfectamente utilizable. Los sistemas de compilación de Java no pueden determinar qué archivos deben volver a compilarse después de un cambio de código. Un IDE determinará qué archivos requieren un cambio de código, pero no cuáles necesitan una nueva compilación. Si la firma de un método cambia, pero el cambio es compatible con el código de la firma anterior (por ejemplo, cambiar un tipo de argumento de flotante a doble), se requiere una compilación limpia para evitar MethodNotFoundException.
Kevin Cline
1
@kevin: Sin embargo, generalmente es posible reconstruir todo sin demasiado costo. A diferencia de C ++ (pero como casi cualquier otro lenguaje compilado en la tierra) Java simplemente no tarda tanto en compilar que la compilación parcial es una optimización muy valiosa de su flujo de trabajo de desarrollo.
Donal Fellows
1
@Donal: Es cierto que Java compila bastante rápido, pero odio adivinar si debo o no hacer una compilación completa. Construye sólo debe trabajar, cada vez.
Kevin Cline
16

No hay una necesidad real en C ++ de tener las definiciones de clase y declaraciones en archivos separados. Simplemente significa que usted podría, al menos en los días C, hacer el análisis en un solo escaneo de arriba a abajo del código. En máquinas sin almacenamiento de acceso aleatorio, ¡esto fue un gran problema!

Tener encabezados también le permitió publicar la interfaz en su biblioteca de códigos al proporcionar el encabezado sin necesidad de revelar el código fuente. Desafortunadamente, en C ++ también tiene que revelar los miembros de datos privados que han llevado a soluciones como el horror de Pimpl .

Ha habido intentos de crear un entorno C ++ donde todo estaba almacenado en una estructura de tipo de base de datos y no hay archivos, pero no se puso al día.

Martin Beckett
fuente
Lo sé, pero al menos puedes hacerlo en C ++ no en Java; Esa fue mi pregunta principal. Gracias por la respuesta.
Etienne Noël
14

Por el principio DRY . En Java, la información necesaria para usar clases en un paquete (o clase) está contenida dentro del archivo .class. Crear archivos de encabezado separados que contengan la misma información implicaría repetirlo en dos lugares.

Jay Elston
fuente
desafortunadamente, a menudo desea repetirlo: piense en archivos wsdl, archivos idl, etc. Uno describe la interfaz que puede usar y otro archivo contiene la implementación. Los encabezados de C ++ son definiciones de interfaz (deficientes).
gbjbaanb
6

En cada idioma, hay dos etapas para crear el código binario final: compilar y vincular (por supuesto, hay carga, pero eso no tiene mucho impacto aquí). En el momento de la compilación, solo es necesario colocar los ganchos (la especificación de las funciones que se llamarán) en el lugar apropiado. Linker realmente se une a ellos cuando ambos códigos reales están disponibles. Hasta ahora no hay diferencia entre C ++ y Java.

Sin embargo, existe la necesidad de que C ++ tenga declaración y definición separadas. Si mantiene la implementación en el encabezado, y si el archivo del encabezado cambia, el código que está vinculado debe volver a compilarse. Donde, como si la definición estuviera en un archivo separado, el código solo necesita volver a vincularse.

Comprenda que C ++ tiene la opción de tener enlaces estáticos, lo que implica que el código objeto se arregla junto con la aplicación que realiza la llamada. Tenga en cuenta que tanto en C como en C ++, no es inválido tener programación en el archivo de encabezado o incluso hacer #include. solo significa que debe preocuparse acerca de cómo ocurre la vinculación con estos archivos de objetos.

La situación en Java es muy diferente. Cada archivo de clase se compila con el archivo .class. De hecho, la necesidad de la compilación de la función de clase de llamador que se sirve como una sección de encabezado en el archivo .class. Sin embargo, en Java el enlace final se realiza solo dentro del Runtime (la máquina virtual) solo con esa especificación del código de bytes del archivo de clase.

Mira esto y esto

Dipan Mehta
fuente
4

Efectivamente, las interfaces e incluye son los encabezados; Por lo tanto, las definiciones son idénticas a los binarios y no pueden estar fuera de sincronización. Esta es una de las mejores decisiones de diseño en Java, pero es una molestia menor que no haya forma de agrupar estas declaraciones para lograr compacidad y consistencia.

ddyer
fuente
1

Una buena razón para tener incluye es separar el código que desee reutilizar (como las definiciones comunes) del código específico de un proyecto determinado. Java quiere que especifique solo una clase o interfaz por archivo y eso reduce la necesidad de encabezados incluidos, ya que tendrá las partes compartidas ya en sus propios archivos.

Además, los compiladores y los sistemas de compilación pueden querer almacenar en caché los encabezados precompilados para evitar analizarlos más de una vez.

rbanffy
fuente
1
Supongo que podría almacenar las interfaces en un proyecto compartido y luego implementarlas en proyectos independientes
Alexander Mills,