Java가 C ++ 에서처럼 헤더 사용을 허용하지 않는 이유


18

요구 사항에 맞지 않는 다음 답변을 제외하고 답변을 찾지 못했다는 질문이 있습니다.

"제임스 고슬링은 원하지 않았기 때문에"

Java는 인터페이스 (순수 가상 함수 만, 속성 없음)를 가질 수 있지만 클래스 정의와 정확히 같은 것은 아닙니다.


14
그들이 원하는 이유는 무엇입니까?

19
swordfights에 대한 더 많은 시간을 갖기 위해;)
dan04

6
대부분의 C ++ 개발자는 모든 cpp 파일에 대해 수백 kLoC를 복제하는 40 년 된 텍스트 대체 엔진을 제거하여 C ++의 긴 컴파일 시간을 원한다고 가정합니다. 실제로 C ++ 11에서는 적절한 모듈 시스템이 고려되었지만 시간 부족으로 인해 중단되었습니다. 그래도 다시 올 것이라고 생각합니다.
sbi

그래도 다시 올 것이라고 생각합니다. 실제로 WG21 (ISO C ++ 워킹 그룹)에는 "모듈"개념을 더 평가 / 개발하기위한 목적으로 만 연구 그룹이 있습니다 : SG2 "모듈". 현재 상태가 휴면 상태입니다 .
Max Truxa 2016 년

답변:


46

내 요구 사항을 충족하지 않는 다음 답변 : "James Gosling이 원하지 않기 때문에."

그래도 정답입니다. 언어 디자인 팀 (Gosling, Sheridan, Naughton, 나중에 Bill Joy, Ken Arnold 등)은 헤더가 해결하는 것보다 더 많은 문제를 야기 한다고 결정했습니다 . 그래서 그들은 그것들을 디자인하고 그것들이 필요없이 완벽하게 유용한 언어를 만들 수 있음을 보여주었습니다.

Java 언어 환경 백서의 2.2.1 섹션 에서 :

Java로 작성된 소스 코드는 간단합니다. 전 처리기, #define 및 관련 기능, typedef 및 해당 기능이 없으며 더 이상 헤더 파일이 필요하지 않습니다. Java 언어 소스 파일은 헤더 파일 대신 다른 클래스 및 해당 메소드의 정의를 제공합니다.

중복 정의, 파일 동기화, 충돌 정의, 숨겨진 정의 유지-헤더가 없기 때문에 Java에서 발생하지 않습니다. 베어 클래스 정의를 보려면 .java 파일에서 직접 클래스 정의를 생성 할 수 있습니다. 예를 들어 대부분의 IDE는 사이드 바의 클래스 구조를 보여줍니다.


6
답에 감사드립니다. 따라서 헤더는 중복 정의, 파일 동기화 유지, 충돌 정의, 숨겨진 정의로 인해 더 많은 문제를 일으켰습니다. 그것이 왜 허용되지 않았습니까?
Etienne Noël

2
다음 C ++ Commitee 회의에 대해서는 많은 이야기가 있습니다. 왜냐하면 그들은 자바, C # 등의 패키지와 비슷한 점이 있지만 여전히 복고풍 인 것보다 더 간단하고 효율적인 시스템 인 새로운 "모듈"시스템을 고려할 것이기 때문입니다. -와 호환됩니다. 즉, 이론 상으로는 더 나은 컴파일 시스템을 사용하여 C ++ 컴파일을 더 좋고 효율적으로 만들 수 있습니다. Gosling이 옳았 고 C ++은 포함 시스템을 수정하는 방법을 찾아야합니다.
Klaim

5
완벽하게 사용할 수있는 것은 아닙니다 . Java 빌드 시스템은 코드 변경 후 재 컴파일해야하는 파일을 판별 할 수 없습니다. IDE는 코드 변경이 필요한 파일을 결정하지만 재 컴파일 할 필요가없는 파일을 결정합니다. 메소드 서명이 변경되었지만 변경 사항이 이전 서명과 코드 호환 가능한 경우 (예 : 인수 유형을 float에서 double로 변경) MethodNotFoundException을 방지하려면 새로 빌드해야합니다.
케빈 클라인

1
@ kevin : 그러나 일반적으로 너무 많은 비용을 들이지 않고 모든 것을 다시 만들 수 있습니다. C ++과는 달리 (그러나 지구상의 거의 모든 다른 컴파일 언어와 마찬가지로) Java는 부분 컴파일이 개발 워크 플로의 매우 가치있는 최적화라는 것을 컴파일하는 데 오래 걸리지 않습니다.
Donal Fellows

1
@Donal : Java가 꽤 빨리 컴파일되는 것은 사실이지만, 전체 재 컴파일을 수행해야하는지 추측하는 것이 싫습니다. 빌드는 항상 작동해야합니다 .
케빈 클라인

16

C ++에서는 클래스 정의와 선언을 별도의 파일로 가질 필요가 없습니다. 그것은 적어도 C 일에 다시 코드의 단일 맨 아래 스캔으로 구문 분석을 수행 할 수 있음을 의미합니다. 랜덤 액세스 스토리지가없는 머신에서 이것은 대단했습니다!

헤더를 사용하면 소스 코드를 공개하지 않고도 헤더를 제공하여 인터페이스를 코드 라이브러리에 공개 할 수 있습니다. 불행히도 C ++에서는 개인 데이터 멤버를 공개해야하므로 pimpl 의 공포와 같은 솔루션으로 이어졌습니다 .

모든 것이 데이터베이스 유형 구조에 저장되고 파일이 없지만 포착되지 않은 C ++ 환경을 만들려고 시도했습니다.


나는 그것을 알고 있지만 적어도 당신은 Java가 아닌 C ++로 할 수 있습니다. 그것은 나의 주요 질문이었다. 답변 해주셔서 감사합니다.
Etienne Noël

14

DRY 원리로 인해 . Java에서는 패키지 (또는 클래스)에서 클래스를 사용하는 데 필요한 정보가 .class 파일에 포함되어 있습니다. 동일한 정보를 포함하는 별도의 헤더 파일을 작성하려면 두 곳에서 반복해야합니다.


불행히도, 종종 반복하고 싶습니다-wsdl 파일, idl 파일 등을 생각하십시오. 하나는 사용할 수있는 인터페이스를 설명하고 다른 하나는 구현을 포함합니다. C ++ 헤더는 (빈약 한) 인터페이스 정의입니다.
gbjbaanb

6

모든 언어에서-최종 바이너리 코드를 생성하기위한 두 단계-컴파일 및 링크 (물론로드는 있지만 여기에는 큰 영향을 미치지 않음)가 있습니다. 컴파일 할 때 적절한 위치 에 후크 (호출 할 함수의 스펙) 만 넣으면 됩니다. 링커 는 실제 코드를 모두 사용할 수있을 때 실제로 연결 됩니다. 지금까지 C ++과 Java 사이에는 차이가 없습니다.

이다 C ++는 선언과 정의 분리를 할 필요가 있지만,. 구현을 헤더로 유지하고 헤더 파일이 변경되면 이와 연결된 코드를 다시 컴파일해야합니다. 정의가 별도의 파일에있는 경우 코드는 다시 연결하기 만하면됩니다.

C ++에는 정적 링크를 위한 옵션이 있는데, 이는 호출하는 응용 프로그램과 함께 오브젝트 코드가 고정됨을 의미합니다. C와 C ++ 둘 다에서 헤더 파일에 프로그래밍을하거나 #include를 수행하는 것은 유효하지 않습니다. 단지이 오브젝트 파일들과의 링크가 어떻게 발생하는지 고민해야한다는 것을 의미합니다.

Java의 상황은 매우 다릅니다. 각 클래스 파일은 .class 파일로 컴파일됩니다. 실제로 .class 파일에서 헤더 섹션으로 제공되는 호출자 클래스 함수 컴파일이 필요합니다. 그러나 Java에서 최종 연결은 클래스 파일의 바이트 코드 사양이 지정된 경우에만 런타임 (가상 머신) 내에서만 수행됩니다.

참조


4

사실상 인터페이스와 포함은 헤더입니다. 따라서 정의는 이진과 동일하며 동기화되지 않을 수 있습니다. 이것은 Java에서 가장 좋은 디자인 결정 중 하나이지만, 소형화 및 일관성을 위해 이러한 선언을 번들로 묶을 방법이 없다는 것은 사소한 일입니다.


1

포함해야 할 한 가지 좋은 이유는 재사용하려는 코드 (예 : 공통 정의)를 주어진 프로젝트에 특정한 코드와 분리하는 것입니다. Java는 파일 당 하나의 클래스 또는 인터페이스 만 지정하기를 원하며 포함 된 헤더의 필요성이 줄어 듭니다. 이미 공유 파트를 자체 파일에 저장하기 때문입니다.

또한 컴파일러와 빌드 시스템은 사전 컴파일 된 헤더를 캐시하여 두 번 이상 구문 분석하지 않도록 할 수 있습니다.


1
인터페이스를 공유 프로젝트에 저장 한 다음 독립적 인 프로젝트로 구현할 수 있다고 가정합니다.
Alexander Mills
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.