JavaがC ++のようにヘッダーの使用を許可しない理由


18

要件を満たさない次の回答を除いて、回答が見つからなかったという質問があります。

「ジェームズゴスリングはしたくなかったから」

Javaにはインターフェース(純粋な仮想関数のみ、属性なし)を含めることができますが、クラス定義とまったく同じではありません。


14
あなたがそれらを望む理由は何ですか?

19
剣闘の

6
ほとんどのC ++開発者は、cppファイルごとに何百ものkLoCを複製する40年前のテキスト置換エンジンを取り除き、C ++の長いコンパイル時間をもたらすことを望んでいると思います。実際、C ++ 11には適切なモジュールシステムが想定されていましたが、時間の不足により削除されました。とはいえ、再び登場すると思います。
SBI

とはいえ、再び登場すると思います。実際、WG21(ISO C ++ワーキンググループ)には、「モジュール」の概念をさらに評価/開発することのみを目的とした研究グループSG2「モジュール」があります。残念なことに、現在のステータスは休止しています。
マックストルシャ

回答:


46

私の要件を満たしていない次の回答:「ジェームズゴスリングはしたくなかったからです。」

しかし、それは正しい答えです。言語設計チーム(Gosling、Sheridan、Naughton、後にBill Joy、Ken Arnoldなど)は、ヘッダーが解決するよりも多くの問題を引き起こすと判断しました。そこで彼らはそれらを設計し、それらを必要とせずに完全に有用な言語を作成できることを実証しました。

Java Language Environmentホワイトペーパーのセクション2.2.1から:

Javaで記述されたソースコードは単純です。プリプロセッサ、#defineおよび関連する機能、typedefがなく、これらの機能がなく、ヘッダーファイルは不要です。Java言語のソースファイルは、ヘッダーファイルの代わりに、他のクラスとそのメソッドの定義を提供します。

冗長な定義、ファイルの同期の維持、競合する定義、非表示の定義-ヘッダーがないため、これらはJavaでは発生しません。裸のクラス定義を表示したい場合は、.javaファイルから直接定義を生成できます。たとえば、ほとんどのIDEは、同じことを行うサイドバーにクラスの構造を表示します。


6
あなたの答えをありがとう、それから、ヘッダーはより多くの問題を引き起こしました:冗長な定義、ファイルの同期を保つ、定義の競合、隠された定義。それが許可されなかった理由ですか?
エティエンヌノエル

2
次のC ++委員会の会議については多くの話があることに注意してください。なぜなら、彼らは(Java、C#などのパッケージといくつかの類似点がある)よりも単純で効率的なシステムであるが、まだレトロな「モジュール」システムを検討するからです-includesと互換性があります。つまり、少なくとも理論上は、より優れたコンパイルシステムを使用して、C ++コンパイルをより優れた/より効率的にすることができます。ゴスリングは正しかったと思うし、C ++はインクルードシステムを修正する方法を見つけなければならない。
クライム

5
完全に使用できるわけではありません。Javaビルドシステムは、コード変更後にどのファイルを再コンパイルする必要があるかを判断できません。IDEはコードの変更が必要なファイルを判別しますが、再コンパイルが必要なファイルは判別しません。メソッドのシグネチャが変更されたが、その変更が古いシグネチャとコード互換性がある場合(引数の型をfloatからdoubleに変更する場合など)、MethodNotFoundExceptionを防ぐためにクリーンビルドが必要です。
ケビンクライン

1
@kevin:ただし、通常は、コストをかけずにすべてを再構築することは可能です。C ++とは異なり(ただし、他のほとんどすべてのコンパイル済み言語と同様)、Javaはコンパイルにそれほど時間がかかりません。その部分的なコンパイルは、開発ワークフローの非常に価値のある最適化です。
ドナルドフェローズ

1
@Donal:Javaがかなり速くコンパイルされるのは事実ですが、完全な再コンパイルを行うべきかどうかを推測するのは嫌です。ちょうど、動作するはずビルドごとに時間を。
ケビンクライン

16

C ++では、クラス定義と宣言を別々のファイルに含める必要はありません。これは、少なくともC時代に戻って、コードの1回の上下スキャンで解析を実行できることを意味します。ランダムアクセスストレージのないマシンでは、これは大したことでした!

ヘッダーがあることで、ソースコードを公開せずにヘッダーを提供することにより、インターフェイスをコードライブラリに公開することもできます。残念ながら、C ++では、pimplの恐怖のようなソリューションにつながったプライベートデータメンバーも明らかにする必要があります。

すべてがデータベース型構造に保存され、ファイルはないがキャッチされなかったC ++環境を作成する試みがありました。


私はそれを知っていますが、少なくともJavaではなくC ++でそれを行うことができます。それが私の主な質問でした。答えてくれてありがとう。
エティエンヌノエル

14

DRY原理のため。Javaでは、パッケージ(またはクラス)内のクラスを使用するために必要な情報は、.classファイル内に含まれています。同じ情報を含む個別のヘッダーファイルを作成するには、2つの場所でそれを繰り返す必要があります。


残念ながら、あなたはしばしばそれを繰り返したいと思います-wsdlファイル、idlファイルなどを考えてください。1つは使用できるインターフェースを記述し、もう1つのファイルは実装を含みます。C ++ヘッダーは(貧弱な)インターフェイス定義です。
-gbjbaanb

6

すべての言語で-最終的なバイナリコードを作成するための2つの段階があります-コンパイルとリンク(もちろん、読み込みはありますが、ここではあまり影響しません)。コンパイル時には、フック(呼び出される関数の仕様)を適切な場所に置くだけで済みます。両方の実際のコードが利用可能な場合、リンカーは実際それらを結合します。これまでのところ、C ++とJavaの間に違いはありません。

そこ宣言と定義別のを持っているC ++の必要性は、しかし、。実装をヘッダーに保持し、ヘッダーファイルが変更された場合、それにリンクされているコードを再コンパイルする必要があります。定義が別のファイルにあるかのように、コードを再リンクするだけで済みます。

C ++には、呼び出し元のアプリケーションと共にオブジェクトコードが修正されることを意味する静的リンクのオプションがあります。CとC ++の両方で、ヘッダーファイルにプログラミングを行ったり、#includeを実行したりすることは無効ではないことに注意してください。これは、これらのオブジェクトファイルでリンクがどのように発生するかを気にする必要があることを意味するだけです。

Javaの状況は非常に異なります。各クラスファイルは、.classファイルでコンパイルされます。確かに、.classファイルのヘッダーセクションとして機能する呼び出し元クラス関数のコンパイルが必要です。ただし、Javaでは、クラスファイルのバイトコードが指定されている場合のみ、最終リンクはランタイム(仮想マシン)内でのみ行われます。

参照してください。この、この


4

事実上、インターフェースとインクルードはヘッダーです。そのため、定義はバイナリと同一であり、同期していないことはありません。これはJavaでの最適な設計上の決定の1つですが、コンパクトさと一貫性のためにこれらの宣言をバンドルする方法がないことはささいな迷惑です。


1

含める理由の1つは、特定のプロジェクトに固有のコードから、再利用したいコード(共通定義など)を分離することです。Javaは、ファイルごとに1つのクラスまたはインターフェースのみを指定することを望みます。これにより、インクルードヘッダーの必要性がほとんど減ります。これは、独自のファイルにすでにある共有部分を用意するためです。

また、コンパイラとビルドシステムは、プリコンパイルされたヘッダーをキャッシュして、複数回解析しないようにしたい場合があります。


1
I共有プロジェクトでのインターフェイスを格納し、独立したプロジェクトでそれらを実装することができたと
アレクサンダー・ミルズ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.