第 5 回 第 3 章継承 91 継承 ( インヘリタンス ): ウインドウシステムを例に説明 図 3.1: ウインドウの中にラベル, ボタン, リストの部品 各部品の属性と操作共通の属性と操作 ウインドウ内の左上を原点として (x, y) で場所指定 : 属性 (width, height) でサイズ指定 : 属性 識別のための名前 (name): 属性 置く位置の指定 (setlocation, setsize): 操作 再描画処理 (repaint): 操作 名前の設定 (setname, getname): 操作ラベルの属性と操作 表示する文字列 (text): 属性 text の設定 (settext, gettext): 操作ボタンの属性と操作 ボタンの上に表示する文字列 (label): 属性 label の設定 (setlabel, getlabel): 操作ボタンの属性と操作 表示する項目 (items): 属性 項目を得る (getitems): 操作 項目を追加する (additem): 操作 項目を削除する (remove): 操作 x 座標は右方向に値が大きく,y 座標は下方向に値が大きくなることに注意. 92
継承 ( インヘリタンス ): ウインドウシステムを例に説明 図 3.1: ウインドウの中にラベル, ボタン, リストの部品 各部品の属性と操作共通の属性と操作 ウインドウ内の左上を原点として (x, y) で場所指定 : 属性 (width, height) でサイズ指定 : 属性 識別のための名前 (name): 属性 置く位置の指定 (setlocation, setsize): 操作 再描画処理 (repaint): 操作 名前の設定 (setname, getname): 操作ラベルの属性と操作 表示する文字列 (text): 属性 text の設定 (settext, gettext): 操作ボタンの属性と操作 ボタンの上に表示する文字列 (label): 属性 label の設定 (setlabel, getlabel): 操作ボタンの属性と操作 表示する項目 (items): 属性 項目を得る (getitems): 操作 項目を追加する (additem): 操作 項目を削除する (remove): 操作 x 座標は右方向に値が大きく,y 座標は下方向に値が大きくなることに注意. 共通点と相違点は? 93 部品の属性と操作の共通点 相違点 表 3.1 部品の共通点 相違点共通点ラベル独自ボタン独自リスト独自 属性 x, y, width, height, name text, label, items, 操作 setlocation(), setsize(), repaint(), setname(), getname(), settext(), gettext(), setlabel(), getlabel(), getitems(), additem(), remove(), 共通部分を抜き出したクラスと, 異なった部分を抜き出したクラスを作成 共通部分を抜き出したクラス : コンポーネント (Component: 構成要素 ) 継承 : 抜き出したクラスに親と子の関係を付ける 子供 ( 例えばラベルクラス ) は親 ( コンポーネントクラス ) の性質 ( 属性と操作 ) を全て引き継ぐ 子供のクラス独自の属性を操作も持つ 94
部品の属性と操作の共通点 相違点 印のついた線で継承の関係を図示親クラス : Component 子クラス : Label, Button, List 親クラス : スーパクラス (superclass) 子クラス : サブクラス (subclass) is a 関係 : スーパクラスとサブクラスの関係 継承の方法具体的なクラスから共通部分を抜き出す : 汎化既にあるクラスを特殊化して継承 : 特化 汎化 95 class サブクラス extends スーパクラス クラス定義の一般形 Java では, サブクラスはスーパクラスの拡張 (extends) であると考えて, キーワードとして extends を使用. 自分で作成するクラスは必ず何らかのクラスのサブクラスでなければならない. extends スーパクラス を省略すると,Java のクラス階層の最上位クラス ( ルート ) である Object クラスのサブクラスとして定義される. 96
JFrame を継承した特化の例 : JFrameTest01.java Java の標準クラスライブラリの Swing(GUI ライブラリ ) JFrame: ウインドウの枠を実現するクラス JPanel: 描画に使用できるクラス 図 3.7 に記載されていない多数のフィールドやメソッドが利用可能. import javax.swing.*; //JFrame を使うため //JFrame を継承した JFrameTest01 クラス public class JFrameTest01 extends JFrame{ public static void main(string[] args){ JFrameTest01 myframe=new JFrameTest01(); myframe.setdefaultcloseoperation (JFrame.EXIT_ON_CLOSE); // 閉じる設定 myframe.setsize(400,300); // ウインドウのサイズ設定 myframe.setvisible(true); // 画面上に可視化 実行結果 97 JFrame を継承した特化の例 //JFrameを継承したJFrameTest01クラス public class JFrameTest01 extends JFrame{ JFrame を継承したサブクラス JFrameTest01 JFrame で定義されている多数のフィールドとメソッドをそのまま使用できる. myframe.setdefaultcloseoperation(jframe.exit_on_close); ウインドウを閉じる ( プログラムを終了する ) ための設定ウインドウ右上の 印をクリックすると終了 JFrameTest01 プログラムには main メソッドしかないが,JFrame クラスを継承しているので, setdefaultcloseoperation() setsize() setvisible() などの JFrame クラスのメソッドを呼び出すことができる. このプログラムには明示されていないが,JFrame オブジェクトが生成されると, 同時に JPanel オブジェクトが 1 つ生成されることになっている.getContentPane() メソッドを使用することで JPanel オブジェクトを参照できる. 98
JPanelTest01.java JPanel を継承して独自の描画を行う例 public class JPanelTest01 extends JFrame{ public JPanelTest01(){ setcontentpane(new MyPanel()); // MyPanel のオブジェクトを contentpane に設定 // コンストラクタ public static void main(string[] args){ JPanelTest01 myframe=new JPanelTest01(); myframe.setdefaultcloseoperation(jframe.exit_on_close); // 閉じる設定 myframe.settitle("jpaneltest01"); // ウインドウのタイトル設定 myframe.setsize(400,300); // ウインドウのサイズ設定 myframe.setvisible(true); MyPanel.java import java.awt.*; // 描画に使う public class MyPanel extends JPanel{ // JPanelを継承 public void paintcomponent(graphics g){ // メソッドのオーバーライド int x=10, y=10; // 上下左右のマージン計算用 int width=getwidth(); // コンポーネントの幅を得る int height=getheight(); // コンポーネントの高さを得る g.setcolor(color.white); // 描画色を白に g.fillrect(x,y,width-x*2,height-y*2); // 塗りつぶしの四角を描画 g.setcolor(color.black); // 描画色を黒に g.drawrect(x,y,width-x*2,height-y*2); // 四角を描画 99 JPanelTest01.java JPanel を継承して独自の描画を行う例 public class JPanelTest01 extends JFrame{ public JPanelTest01(){ setcontentpane(new MyPanel()); // MyPanel のオブジェクトを contentpane に設定 // コンストラクタ MyPanel.java public static void main(string[] args){ JPanelTest01 myframe=new JPanelTest01();... import java.awt.*; // 描画に使う public class MyPanel extends JPanel{ // JPanel を継承 public void paintcomponent(graphics g){ // メソッドのオーバーライド... JPanelTest01プログラムを実行すると,MyPanelオブジェクトが生成され,contentPaneに設定 JPanelクラスのpaintComponentメソッドは, ウインドウの最小化 復帰 など再描画が必要となるイベントが発生した際に呼び出されるメソッド ( デフォルトではcontentPaneに設定されたオブジェクトを背景色で塗りつぶす ) paintcomponentメソッドをユーザが作成したmypanelクラスで定義し直すことにより, ユーザ独自の描画を行うことができる. スーパクラス (JPanel) のメソッド (paintcomponent) をサブクラス (MyPanel) で定義し直す メソッドのオーバーライド (override) 100
JPanelTest01.java の実行結果 paintcomponent メソッドのパラメータ Graphics オブジェクトには, 様々な描画メソッドが用意 クラス図からは, スーパクラス ( 大元のスーパークラスは JComponent) のメソッド (paintcomponent) をサブクラス (MyPanel) でオーバーライド (override) していることが分かる. 101 JPanelTest02.java public class JPanelTest02 extends JFrame{ public JPanelTest02(){ setcontentpane(new MySubPanel()); MyPanel を継承して独自の描画を行う例 public static void main(string[] args){ JPanelTest02 myframe=new JPanelTest02(); myframe.setdefaultcloseoperation(jframe.exit_on_close); // 閉じる設定 myframe.settitle("jpaneltest02"); // ウインドウのタイトル設定 myframe.setsize(400,300); // ウインドウのサイズ設定 myframe.setvisible(true); // 画面上に可視化 今度は,MySubPanel オブジェクトを作成 102
MySubPanel.java サブクラスのメソッドをオーバーライドした場合 import java.awt.*; // 描画に使う public class MySubPanel extends MyPanel{ // MyPanelを継承 public void paintcomponent(graphics g){ // メソッドのオーバーライド int width=getwidth(); // コンポーネントの幅を得る int height=getheight(); // コンポーネントの高さを得る int r; // 幅と高さの短い方を円の半径として使う if(width>height){ r=height*3/4/2; else{ r=width*3/4/2; g.setcolor(color.blue); // 描画色を青に g.filloval(width/2-r,height/2-r,r*2,r*2); // 塗りつぶしの円を描画 この場合,MyPanel クラスの paintcomponent() メソッド ( 白く塗りつぶした四角を描いてから黒い四角を描く ) がオーバーライドされているので,MySubPanel クラスの paintcomponent() メソッド ( 青く塗りつぶした円 ) だけが実行される. 103 MySubPanel.java スーパクラスのメソッドをオーバーライドした場合 import java.awt.*; // 描画に使う public class MySubPanel extends MyPanel{ // MyPanelを継承 public void paintcomponent(graphics g){ // メソッドのオーバーライド super.paintcomponent(g); // スーパクラスのメソッド呼び出し int width=getwidth(); // コンポーネントの幅を得る int height=getheight(); // コンポーネントの高さを得る int r; // 幅と高さの短い方を円の半径として使う if(width>height){ r=height*3/4/2; else{ r=width*3/4/2; g.setcolor(color.blue); // 描画色を青に g.filloval(width/2-r,height/2-r,r*2,r*2); // 塗りつぶしの円を描画 オーバーライドしたメソッド ( この場合は MySubPanel クラスの paintcomponent() メソッド ) の中からスーパクラス (MyPanel クラス ) のメソッドを呼び出すと機能の拡張が実現できる. この場合は, MyPaint クラスのメソッド : 白く塗りつぶした四角を描いてから黒い四角を描く MySubPaint クラスのメソッド : 青く塗りつぶした円を描くの両方が実行される. 104
MyPanel を継承して独自の描画を行う例 スーパクラスのメソッドをオーバーライド オーバーライドしたサブクラスのメソッド中からスーパクラスのメソッドを呼び出し 105