目次 | 前項目 | 次項目 内部クラス仕様


なぜ Java が内部クラスを必要とするのか?

Java の当初から、その設計者は「メソッドポインタ」のような構築物の必要を認識していました。これは(その様々な形式すべてにおいて)帰するところ、そのコードを含むオブジェクトまたはクラスを参照せずに使用できる個別ブロックのコードのハンドルになります。関数がオブジェクトと独立に自由に存在している(C または Lisp のような)言語では、関数ポインタがこの役割を担っていました。例えば、これらのポインタは 1 つのモジュール内の「コールバック」または「イベント」を他のコードの一部に接続する役を、しばしば果します。もっとオブジェクト志向の型では、Smalltalk は小さなオブジェクトのように動作するコードの固まりである「ブロック」を持っています。C または Lisp 関数ポインタに関すると同様に、Smalltalk ブロックは集合上の繰り返しなどの複雑な制御フローパターンを編成するために使用できます。

Java では、イベント管理と繰り返しを含む同じ複雑な制御フローパターンは、クラスとインタフェースによって表現します。Java は、他の言語が別個の「関数型」を使用するようなところで、 1 つのメソッドを持ったインタフェースを使用します。Java プログラマは、希望するコードを必要なインタフェースを実装するアダプタクラス内でラップすることによって、コールバックまたは Smalltalk ブロックに相当するものを作成します。内部クラスに関しては、アダプタの表記法は Smalltalk ブロックまたは他の言語の内部関数とほぼ同じくらい簡単です。しかし、クラスは関数より豊かであるため(複数エントリポイントを持つため)、Java アダプタオブジェクトは関数ポインタより強力で構造化されています。

C、Lisp、および Smalltalk プログラマは、コードの固まりをカプセル化するためにさまざまな「メソッドポインタ」を使用しますが、Java プログラマはオブジェクトを使用します。他の言語は動作を関数としてカプセル化するために、特別の関数型および表記法を持っていますが、Java はクラスとインタフェース型を持っているだけです。Java では、「クラスは動作の量子です」。このアプローチの 1 つの利点は、単純さおよび内部クラスまたは関数ポインタの特別なサポートを必要としない Java Virtual Machine に対する安定性です。

内部クラスなしで、Java プログラマはトップレベルで定義したアダプタクラスによって、コールバックと iterators を作成できますが、表記法は非常にぎこちなく非実際的です。内部クラスによって、Java プログラマは簡潔なアダプタクラスを書くことができます。このアダプタクラスは必要な場所で正確にコード化され、直接内部変数およびクラスやブロックのメソッド上で動作します。

こうして、内部クラスはアダプタクラスをコーディングスタイルとして実際的にします。将来、内部クラスはまた、最適化の機会増大、特に(外部的に)アクセス不可能クラスのおかげで、同等のトップレベルアダプタクラスより効率的になります。

なぜ匿名クラスなのか?

匿名クラスは、希望するコードを式 "new" 内でラップすることによって、どの式内にも簡単なローカルオブジェクト「インライン」を作成する省略表記法です。

以前に注意したように、すべての内部クラスが匿名である必要はありませんが、非常に簡単な「一度だけの」ローカルオブジェクトは、構文の恩恵にあずかる共通のケースです。

匿名クラスは、 enumerations、iterators、visitors など小さなカプセル化された「コールバック」を書くために有用です。これらはまた、AWT コンポーネント(匿名イベントハンドラがこれに追加される)およびスレッドなどの、既に名前を持っているオブジェクトに動作を追加するための手助けになります。両方のケースで、介在するクラス名はコードの明瞭さを減じることができます。

Smalltalk および Beta など、Java がヒントを得たいくつかの他の言語は、匿名オブジェクトまたは関数の同様な表記法を提供します。

動的型割当および計算済セレクタ("perform")はどうなのか?

強力で安全なシステムの構築をサポートするために、Java は静的な型になっています。他の言語では、コールバックは時々型割当なし、または動的型割当の形式を取ります。C のコールバックは通常型割当なしの「クライアントデータ」アドレスに働きかけ、他方 Smalltalk のクラスは時々、解釈用の "perform" メソッドに渡される、実行時に計算されるシンボリックメソッド参照によってお互いにプラグインします。

Java で C void* ポインタに最も近いものは、型 Object の参照です。C と同様、Java でこのような「型割当なしの」参照をプログラムすることは可能です。イベント記述子内の一般的な「引数」フィールドは、java.util.Vector の要素型であると同様に、差別化されていない Object である可能性があります。型割当なしの参照でコーディングすることは、動的型検査の実行費用に関わらず、時に実行可能な技術です。しかし、静的宣言の欠如によって、プログラムが理解と維持しにくくなります。

また、アプリケーションビルダや Java Beans コンポーネントフレームワークなどの、「メソッドポインタ」構築物用のいくつかのアプリケーションには、任意のオブジェクト上の計算済名のメソッドを起動する機能が必要になります。この機能は、Java 1.1 API の Java Core Reflection API、java.lang.reflect によって提供されます。


目次 | 前項目 | 次項目

内部クラス仕様 (HTML generated by dkramer on March 15, 1997)
Copyright (c) 1996, 1997 Sun Microsystems, Inc. All rights reserved
コメントや訂正は john.rose@eng.sun.com 宛てに送ってください。