前回はJFrameというもともとあるクラスをそのまま利用しました。Javaにはこの他に、元のクラスに自分で機能を付け加えて新たに別のクラスをつくって使うという使い方があります。これを継承といいます。
前回は javax.swing の中にある、JFrame というクラス(ライブラリ)を使って、フレームを作りました。
使用法は new JFrame() を使用して自分が利用するフレームを作って myframe と名前を付け、それに対して、myframe.setSize() のように指示をだすというものでした。
/* フレームを作成 */ JFrame myframe = new JFrame(); /* サイズを指定 */ myframe.setSize(400, 300); /* 終了処理を設定 */ myframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); /* 実際に表示する */ myframe.setVisible(true);
オブジェクト指向の言葉では、new JFrame() をコンストラクタを使って、インスタンスをつくり、setSize などのメソッドを使って、設定をしたということになります。setSizeなどはもともと JFrame というクラスにある機能でJFrameのインスタンスを作ることで、適用できるようになります。
クラスは自分で作成して利用することもできます。(というより、java のプログラミングはクラスの作成そのものですが)そのとき、すでにあるクラスに、必要な機能を付け加えて利用することができます。この時もともとのクラスの持っている機能はそのまま使えます。これを継承 と呼びます。
継承によってできたクラスをサブクラス、元になったクラスをスーパークラスといいます。サブクラスの方が拡張されている分、機能的にはスーパーなのですが、名前がサブ。機能と名前のイメージが違うので注意が必要です。
import javax.swing.*;
/** JFrame の拡張 */
public class ExFrame01 extends JFrame{
/** コンストラクタ ************/
public ExFrame01(){
/* サイズを指定 */
setSize(400, 300);
/* 終了処理を追加 */
setDefaultCloseOperation(EXIT_ON_CLOSE);
/* 実際に表示する */
setVisible(true);
}
/** mainがないので直接実行できない****/
}
このプログラムはmainがありませんから実行できません。
extends JFrameは、ExFrame01 が JFrame を継承してつくったことを宣言します。
次の行、public ExFrame01(){ で始まるブロックはコンストラクタといい、あとで new でオブジェクトが作られるときにどのような機能を持たせるかの定義を行う部分です。いわばオブジェクトの設計図です。
JFrameには大きさの指定がなく。オブジェクトを作ってからあとで myframe.setSize(400, 300);で指定しました。ここではコンストラクタにsetSize(400, 300);を書いて、いちいち指示しなくてもよくしました。また、[×]ボタンで終了することや、見えるようにすることもいちいち指示しなくてもよくしました。
もともとJFrameを継承しているのでこのコンストラクタはJFrameのコンストラクタを使ってフレームを作ります。これは書かなくてもいいので楽です。その上にいろいろ付け加えて拡張機能をもったExFrame01クラスを作ったということになります。
JFrame というクラスを使うのに new JFrame() とやったように、ExFrame01() を使うのも new ExFrame01() とします。
public class UseExFrame01 { public static void main(String[] args){ /* 拡張されたフレームを作成 */ ExFrame01 myframe = new ExFrame01(); } }
main の中にはたったひとつ、ExFrame01クラスのオブジェクトを new を使って生成しそれにmyframeという名前を付けているだけです。これで ExFrame01 のコンストラクタが呼び出され、拡張されたフレームが作られ、表示までされます。
前回のプログラムと全く同じ機能です。結果だけ見ればつまらないですし、プログラムの中身も似たようなものに写るかも知れません。でも考え方はまるで違います。
それは自分のクラスライブラリを作ったからです。
UseExFrame01.java の main は new ExFrame01() だけなので、わざわざ別のファイルを作るのは面倒です。そこで ExFrame01.java に main を書いてしまうことができます。
import javax.swing.*; /** JFrame の拡張 */ public class ExFrame01 extends JFrame{ /** コンストラクタ ************/ public ExFrame01(){ /* サイズを指定 */ setSize(400, 300); /* 終了処理を追加 */ setDefaultCloseOperation(EXIT_ON_CLOSE); /* 実際に表示する */ setVisible(true); } /** main ***********************/ public static void main(String[] args){ /* 拡張されたフレームを作成 */ ExFrame01 myframe = new ExFrame01(); } }
コンストラクタのブロックの後に main の部分を書きました。javaではプログラムを実行するときに、この main から始めます。この上にあった ExFrame01のコンストラクタは main の中から呼ばれて実行されます。
前回 JFrame を利用したと同様に ExFrame01 を使うことができるのです。今回は動作テストのため、たいした機能を拡張していませんが、この方法は大規模なプログラムを作るときは大変な力になります。
大規模なプログラムでは、main のないクラスをたくさん作って他のプログラムのmainから呼び出すようにします。小さなプログラムの場合は、面倒なのでmainもひとつのファイルにまとめてしまいます。
しかし、大きなプログラムでも、起動するだけのmainを作ってテスト用にしておくと便利なことがあります。
作成するクラスにどのような機能をもたせ、どの部分を main から指定していくか、これはとても大事なことです。これを上手に設計するとプログラムの流れが理解しやすくなり、間違いのないプログラムを書くことができます。
上記の ExFrame01.java と UseExFrame01.java を両方つくり、UseExFrame01.javaを実行してみなさい
ExFrame01.javaの中にmainを入れてExFrame01.javaを直接実行できるようにしなさい。
2.の ExFrame01.java に書き加えてフレームを2つ作る ExFrame02.java にしなさい。(継承でなく単なる書き加え)
フレームの位置を指定しないと、全く同じところに2つフレームを作るのでわからないかも知れません。タイトルバーをドラッグして、2つになっていることを確認しなさい。
この場合も、setLocation(10, 20) などのメソッドを使って、位置をずらすこともできますが、コンストラクタ内に書くとみんな同じになりますから、結局重なります。
解決策は2つ。
(1) main の中で、myframe.setLocation(10, 20); として変更できます。setLocation は、JFrameクラスのメソッドですが、ExFrame02 は JFrame を継承しているので、このメソッドが含まれています。myframe はExFrame のインスタンスなのでこのメソッドを使えます。
(2)フレームの場所をOS(windowシステム)任せにできます。コンストラクタ内に次のように書けば、少し(タイトルバーの幅程度)ずらして表示します。この場合はコンストラクタ内に書いても場所が変わります。
setLocationByPlatform(true);