オブジェクト指向言語論 第十一回 知能情報学部 新田直也
多態性(最も単純な例) 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 Test A a m() A a A1 m() A2
多態性の使い方1 異なる種類のオブジェクトに一括して処理を行う場合 →図形はすべて移動することができる. →移動の処理は図形ごとに異なる. →実行時までどのクラスのオブジェクトが選択されるか不明. クラス 移動 選択 図形 三角 四角 円
多態性の使い方2 クラス定義: class Shape { // 図形クラス void move(int x, int y) { // 移動メソッド : } class Trianle extends Shape { // 三角形クラス void move(int x, int y) { // 移動メソッドをオーバーライド class Rectangle extends Shape { // 四角形クラス
多態性の使い方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; 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; 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; }
クラス変数,クラスメソッド クラス変数: クラスが持つ変数.全インスタンスで値を共有できる. クラスメソッド: インスタンスを指定せずに呼び出せるメソッド.内部ではクラス変数にしかアクセスできない. 使用例: class A { static int MAX_NUM = 1000; static int getMaxNum() { return MAX_NUM; } n = A.getMaxNum();
修飾子のまとめ よりオブジェクト指向らしいプログラムのために… 修飾子: 抽象メソッド,抽象クラス abstract アクセスレベル public,protected,private クラス変数,クラスメソッド static