last modified: Feb./4th/2002
前節ではリスナーを別のクラスに分離しました。そのために、アプレットを操作するために双方のクラスにフィールドを作る必要がありました。本節では、その面倒を回避する為に、内部クラスを利用します。クラス内部に記述されたクラスは、その外側の包含クラス (enclosing class) のフィールドとメソッドをダイレクトに利用することが出来ます。ブロック内に記述した場合は、包含ブロックのスコープ内のローカル変数も自由に使うことが出来ます。
オブジェクト指向言語は、構造化を推し進めた結果、階層化とコンポーネントの分離が進んだ産物だといえます。パッケージ、クラスの継承などの階層が存在しますが、内部クラスも階層化の一つの例です。
一般に、或るクラスやインタフェースに包含されたクラスのことを「ネストされたクラス」 (nested class) と呼びます。この中で、修飾子に static
が付かず、インスタンス化可能な「ネストされたクラス」を内部クラス (inner class) と呼びます。
内部クラスでは次の二点が本質的に重要です:
Sun Microsystems によれば、「ネストされたクラス」と言えば、構造上包含クラス内部に記述されたクラスのことを指し、「内部クラス」と言えば、包含クラスのインスタンス内部のインスタンスと考えるように示唆されています。
次の例は、テキストフィールドの数字を半径とする円の面積を計算するものです。
import java.applet.*; import java.awt.*; import java.awt.event.*; public class InnerClass extends Applet { private TextField tfRadius; private Button btn; private TextField tfArea; //アプレットの初期化 public void init() { //部品の作成 Label label = new Label("半径"); tfRadius = new TextField(); btn = new Button("面積"); tfArea = new TextField(); //部品の配置/大きさの指定 label.setBounds(20,20,40,20); tfRadius.setBounds(70,20,60,20); btn.setBounds(50,50,50,20); tfArea.setBounds(20,80,110,20); //イベントリスナーの登録 EventHandler eh = new EventHandler(); btn.addActionListener(eh); //部品の配置 this.setLayout(null); this.add(label); this.add(tfRadius); this.add(btn); this.add(tfArea); } //イベント処理用の内部クラス class EventHandler implements ActionListener { public void actionPerformed(ActionEvent e) { //半径の入力欄から面積計算メソッドへの受け渡し String rStr = tfRadius.getText(); tfArea.setText("計算不能"); //I.E., N.C はこの行で止まってしまう //Opera, Netscape6, appletviewer などは O.K. double r = Double.parseDouble(rStr); double d = r*r*Math.PI; String ret = Double.toString(d); tfArea.setText(ret); } } }
内部クラスもコンパイル時にバイトコードが独立したクラス・ファイルに出力されます。今の例では、"InnerClass$EventHandler.class
" です。一般に、内部クラスファイル名は "包含クラス名$内部クラス名.class
" になります。
内部クラスからは、包含クラスのフィールド、メソッドを自由に利用することが出来ます。包含クラスで private
宣言されていても特別の手続きなく利用できます。
特に、 GUI のイベント処理では、イベント代理モデルの必要性から、内部クラスがよく用いられます。本節のサンプルは、 GUI のイベント処理の一つの典型です。
<applet code="InnerClass.class" width="150" height="120"> アプレットが実行できない場合の代替内容。 </applet>
アプレット: InnerClass.class |
このアプレットは、Sun Microsystems が提供している Java Plugin が無いと動作しません。