オブジェクト指向 言語 論 第八回 知能情報学部 新田直也
多相性(最も単純な例) class A { void m() { System.out.println( “ this is class A ” ); } } class A1 extends A { void m() { System.out.println( “ this is class A1 ” ); } } class A2 extends A { void m() { System.out.println( “ this is class A2 ” ); } } class Test { main () { A a = new A1(); a.m();// “ this is class A1 ” と表示 a = new A2(); a.m();// “ this is class A2 ” と表示 } A A1 派生 A2 派生
A a 多相性の考え方 メッセージを送る人は送り先の具体的なクラス ( 具象クラス ) を知らなくてもよい. 実際に呼ぶメソッドは実行時に決まる ( 遅延束縛 ) . A A a A1 Test A2 A a m()
多相性の使い方 1 異なる種類のオブジェクトに一括して処理を行う場合 → 図形はすべて移動することができる. → 移動の処理は図形ごとに異なる. → 実行時までどのクラスのオブジェクトが選択されるか不 明. 四角 三角 クラス 図形 選択 移動 円
多相性の使い方 2 クラス定義: class Shape {// 図形クラス void move(int x, int y) {// 移動メソッド : } class Trianle extends Shape {// 三角形クラス void move(int x, int y) {// 移動メソッドをオーバーライド : } class Rectangle extends Shape {// 四角形クラス void move(int x, int y) {// 移動メソッドをオーバーライド :
多相性の使い方 3 選択図形の移動: // 選択図形の配列を取得(図形の具象クラスは不明) Shape [] sel_obj = GetSelectedObjects(); // 配列中の各要素を移動する for (int n = 0; n < sel_obj.length; n++) { sel_obj[n].move(x, y); } Shape クラス の参照変数の 配列 多相性により Shape クラスまたは子クラス の move メソッドが呼 ばれる Shape sel_obj[n]
本日の目標 多相性を使って,図形を表示するアプリケー ションを作ってみよう !! 仕様: 図形の種類は,正三角形と正方形,円の3種類であ る. 任意の位置に任意の種類の図形を,任意の大きさで, 任意個配置できる. 配置した図形はすべて表示される.
図形クラスの定義( 1 ) 抽象メソッド: 実体を持たないメソッド. abstract 修飾子を付ける. メソッドの実装は派生クラスに任せる. 抽象クラス: 抽象メソッドを 1 つ以上持つクラス.抽象クラスはインス タンス化できない.(継承しなければ使えない.) abstract class Shape {// 抽象図形クラス abstract void view(Graphics g);// 抽象表示メソッド } → Shape クラスはインスタンス化できない.
図形クラスの定義( 2 ) 三角形クラス class Trianle extends Shape {// 三角形クラス int x1, y1; int x2, y2; int x3, y3; void Triangle(int px1, int py1, …) {// コンストラクタ x1 = px1; y1 = py1; : } void view(Graphics g) {// 表示メソッド g.drawLine(x1, y1, x2, y2); g.drawLine(x2, y2, x3, y3); g.drawLine(x3, y3, x1, y1); }
図形クラスの定義( 3 ) 矩形クラス class Rectangle extends Shape {// 矩形クラス int x1, y1; int x2, y2; void Rectangle(int px1, int py1, …) {// コンストラクタ x1 = px1; y1 = py1; : } void view(Graphics g) {// 表示メソッド g.drawLine(x1, y1, x2, y1); g.drawLine(x2, y1, x2, y2); g.drawLine(x2, y2, x1, y2); g.drawLine(x1, y2, x1, y1); }
図形クラスの定義( 4 ) 円クラス class Circle extends Shape {// 円クラス int x1, y1; int r; void Circle(int px1, int py1, int pr) {// コンストラクタ x1 = px1; y1 = py1; r = pr; } void view(Graphics g) {// 表示メソッド g.drawOval(x1-r, y1-r, x2+r, y1+r); }
図形の一括描画 多相性を用いると,図形の種類に関係なく描画できる. class GraphicWindow extends Frame {// Window のクラス : void paint(Graphics g) {// Window を描画する度に呼ばれる Shape[] objList = new Shape[3]; objList[0] = new Circle(120,120,50); objList[1] = new Triangle(20,100,50,50,80,100); objList[2] = new Rectangle(200,50,250,100); for (int i = 0; i < objList.length; i++) { objList[i].view(g); } 配列のサイズを取得できる 多態性により実際のクラスの view() が呼ばれる
アクセスレベル 各メソッドやメンバ変数に対して外部からのアクセスを 許可 / 不許可できる. アクセス修飾子: public : 無制限に公開. protected : ほぼ無制限に公開. private : 同じクラス内からしかアクセスできない. 使用法: 基本的にメソッドは, public で宣言する. public void view(Graphic g) { … 基本的にメンバ変数は, private で宣言する. private int x; 基本的にメンバ変数へのアクセスはメソッドを通じて間接的に 行う. public void setX(int px) { x = px; } public int getX() { return x; }
クラス変数,クラスメソッド クラス変数: クラスが持つ変数.全インスタンスで値を共有できる. クラスメソッド: インスタンスを指定せずに呼び出せるメソッド.内部で はクラス変数にしかアクセスできない. 使用例: n = A.getMaxNum(); class A { static int MAX_NUM = 1000; static int getMaxNum() { return MAX_NUM; }
修飾子のまとめ よりオブジェクト指向らしいプログラムのため に … 修飾子: 抽象メソッド,抽象クラス abstract アクセスレベル public , protected , private クラス変数,クラスメソッド static