プロ2 > 資料 > 第5章

第5回:多相性とその活用

目標

5.1 インタフェースと多相性

import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; public class Sample51 extends JPanel { ArrayList<Figure> figs = new ArrayList<Figure>(); //Figure型のArrayListを生成. Figure sel = null; //クリックされた図形を保存するための変数 public Sample51() { setOpaque(false); figs.add(new Circle(Color.PINK, 200, 100, 40)); //ArrayListに要素を挿入する. figs.add(new Circle(Color.GREEN, 220, 80, 30)); figs.add(new Rect(Color.YELLOW, 240, 60, 30, 40)); figs.add(new Rect(Color.BLUE, 260, 40, 80, 40)); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent evt) { sel = pick(evt.getX(), evt.getY()); //クリックされた図形を選択 } }); addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent evt) { if (sel == null) { //クリックされた図形がなければ何もしない return; } sel.moveTo(evt.getX(), evt.getY()); //クリックされた図形を移動させる repaint(); } }); } private Figure pick(int x, int y) { Figure p = null; for (Figure f : figs) { //ArrayListの要素のそれぞれに対して繰り返し if (f.hit(x, y)) { //座標(x,y)に図形が存在すればそれを返す. p = f; } } return p; } public void paintComponent(Graphics g) { for (Figure f : figs) { //ArrayListの要素のそれぞれを描画する f.draw(g); } } public static void main(String[] args) { JFrame app = new JFrame(); app.add(new Sample51()); app.setSize(400, 300); app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); app.setVisible(true); } interface Figure { //Figureのインタフェース宣言 public void draw(Graphics g); //図形の描画 public boolean hit(int x, int y); //図形がクリックされたかの判定 public void moveTo(int x, int y); //図形の移動 } static class Circle implements Figure { //CircleクラスがFigureインタフェースに従うことを宣言 Color col; int xpos, ypos, rad; public Circle(Color c, int x, int y, int r) { col = c; xpos = x; ypos = y; rad = r; } public boolean hit(int x, int y) { //必須メソッド return (xpos - x) * (xpos - x) + (ypos - y) * (ypos - y) <= rad * rad; } public void moveTo(int x, int y) { //必須メソッド xpos = x; ypos = y; } public void draw(Graphics g) { //必須メソッド g.setColor(col); g.fillOval(xpos - rad, ypos - rad, rad * 2, rad * 2); } } static class Rect implements Figure { //RectクラスがFigureインタフェースに従うことを宣言 Color col; int xpos, ypos, width, height; public Rect(Color c, int x, int y, int w, int h) { col = c; xpos = x; ypos = y; width = w; height = h; } public boolean hit(int x, int y) { //必須メソッド return xpos - width / 2 <= x && x <= xpos + width / 2 && ypos - height / 2 <= y && y <= ypos + height / 2; } public void moveTo(int x, int y) { //必須メソッド xpos = x; ypos = y; } public void draw(Graphics g) { //必須メソッド g.setColor(col); g.fillRect(xpos - width / 2, ypos - height / 2, width, height); } } }
import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; public class Ex51ab extends JPanel { ArrayList<Figure> figs = new ArrayList<Figure>(); Figure sel = null; public Ex51ab() { setOpaque(false); figs.add(new Circle(Color.PINK, 200, 100, 40)); figs.add(new Circle(Color.GREEN, 220, 80, 30)); figs.add(new Rect(Color.YELLOW, 240, 60, 30, 40)); figs.add(new Rect(Color.BLUE, 260, 40, 80, 40)); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent evt) { sel = pick(evt.getX(), evt.getY()); if (sel != null) { //クリックした図形を前面に表示する figs.remove(sel); //クリックした図形をArrayListから削除する. figs.add(sel); //クリックした図形をArrayListに加える. repaint(); } else { //図形のないところクリックすると新たな円を生成する Color c = Color.getHSBColor((float) Math.random(), 1f, 1f); //色をランダムに指定する sel = new Circle(c, evt.getX(), evt.getY(), 30); //円を生成する figs.add(sel); //円をArrayListに加える repaint(); } } }); addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent evt) { if (sel == null) { return; } sel.moveTo(evt.getX(), evt.getY()); repaint(); } }); } /* 以下は同じ */ private Figure pick(int x, int y) { Figure p = null; for (Figure f : figs) { if (f.hit(x, y)) { p = f; } } return p; } public void paintComponent(Graphics g) { for (Figure f : figs) { f.draw(g); } } public static void main(String[] args) { JFrame app = new JFrame(); app.add(new Ex51ab()); app.setSize(400, 300); app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); app.setVisible(true); } interface Figure { public void draw(Graphics g); public boolean hit(int x, int y); public void moveTo(int x, int y); } static class Circle implements Figure { Color col; int xpos, ypos, rad; public Circle(Color c, int x, int y, int r) { col = c; xpos = x; ypos = y; rad = r; } public boolean hit(int x, int y) { return (xpos - x) * (xpos - x) + (ypos - y) * (ypos - y) <= rad * rad; } public void moveTo(int x, int y) { xpos = x; ypos = y; } public void draw(Graphics g) { g.setColor(col); g.fillOval(xpos - rad, ypos - rad, rad * 2, rad * 2); } } static class Rect implements Figure { Color col; int xpos, ypos, width, height; public Rect(Color c, int x, int y, int w, int h) { col = c; xpos = x; ypos = y; width = w; height = h; } public boolean hit(int x, int y) { return xpos - width / 2 <= x && x <= xpos + width / 2 && ypos - height / 2 <= y && y <= ypos + height / 2; } public void moveTo(int x, int y) { xpos = x; ypos = y; } public void draw(Graphics g) { g.setColor(col); g.fillRect(xpos - width / 2, ypos - height / 2, width, height); } } }

5.2 継承によるくくり出しと抽象クラス

import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.util.*; public class Sample52 extends JPanel { ArrayList<Figure> figs = new ArrayList<Figure>(); Figure sel = null; public Sample52() { setOpaque(false); figs.add(new Circle(Color.PINK, 200, 100, 40)); figs.add(new Circle(Color.GREEN, 220, 80, 30)); figs.add(new Rect(Color.YELLOW, 240, 60, 30, 40)); figs.add(new Rect(Color.BLUE, 260, 40, 80, 40)); addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent evt) { sel = pick(evt.getX(), evt.getY()); } }); addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged(MouseEvent evt) { if (sel == null) { return; } sel.moveTo(evt.getX(), evt.getY()); repaint(); } }); } private Figure pick(int x, int y) { Figure p = null; for (Figure f : figs) { if (f.hit(x, y)) { p = f; } } return p; } public void paintComponent(Graphics g) { for (Figure f : figs) { f.draw(g); } } public static void main(String[] args) { JFrame app = new JFrame(); app.add(new Sample52()); app.setSize(400, 300); app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); app.setVisible(true); } interface Figure { public void draw(Graphics g); public boolean hit(int x, int y); public void moveTo(int x, int y); } static abstract class SimpleFigure implements Figure { //抽象クラスの定義 Color col; //クラス共通の変数 int xpos, ypos; public SimpleFigure(Color c, int x, int y) { //抽象クラスのコンストラクタ col = c; xpos = x; ypos = y; } public void moveTo(int x, int y) { //クラス共通のメソッド xpos = x; ypos = y; } public abstract boolean hit(int x, int y); //ここは継承したクラスで定義する public abstract void draw(Graphics g); //ここは継承したクラスで定義する } static class Circle extends SimpleFigure { //SimpleFigureを継承する int rad; //Circleクラス固有の変数 public Circle(Color c, int x, int y, int r) { super(c, x, y); //SimpleFigureのコンストラクタを実行する rad = r; } public boolean hit(int x, int y) { return (xpos - x) * (xpos - x) + (ypos - y) * (ypos - y) <= rad * rad; } public void draw(Graphics g) { g.setColor(col); g.fillOval(xpos - rad, ypos - rad, rad * 2, rad * 2); } } static class Rect extends SimpleFigure { //SimpleFigureを継承する int width, height; //Rectクラス固有の変数 public Rect(Color c, int x, int y, int w, int h) { super(c, x, y); //SimpleFigureのコンストラクタを実行する width = w; height = h; } public boolean hit(int x, int y) { return xpos - width / 2 <= x && x <= xpos + width / 2 && ypos - height / 2 <= y && y <= ypos + height / 2; } public void draw(Graphics g) { g.setColor(col); g.fillRect(xpos - width / 2, ypos - height / 2, width, height); } } }

5.3 型の判定と行き来

import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import javax.swing.JFrame; import javax.swing.JPanel; public class Sample53a extends JPanel { ArrayList<Figure> figs = new ArrayList<Figure>(); boolean turn = true; //手番を示す変数 public Sample53a() { for (int i = 0; i < 9; ++i) { //3×3のマス目の生成 int r = i / 3, c = i % 3; figs.add(new Rect(Color.PINK, 80 + r * 60, 40 + c * 60, 56, 56)); } figs.add(new Text(300, 100, "の手番", new Font("serif", Font.BOLD, 20))); figs.add(new Batsu(300, 40, 24)); //マス目の横にXマークの生成 setOpaque(false); addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent evt) { Rect r = pick(evt.getX(), evt.getY()); if (r == null) { return; } figs.remove(figs.size() - 1); //最後の図形を削除する if (turn) { figs.add(new Batsu(r.getX(), r.getY(), 24)); //マス目にXマーク figs.add(new Maru(300, 40, 24)); //マス目の横に○マークの生成 } else { figs.add(new Maru(r.getX(), r.getY(), 24)); //マス目に○マーク figs.add(new Batsu(300, 40, 24)); //マス目の横にXマークの生成 } turn = !turn; //手番の交替 repaint(); } }); } public Rect pick(int x, int y) { Rect r = null; for (Figure f : figs) { if (f instanceof Rect && ((Rect) f).hit(x, y)) { //マス目かどうかの確認 r = (Rect) f; } } return r; } public void paintComponent(Graphics g) { for (Figure f : figs) { f.draw(g); } } public static void main(String[] args) { JFrame app = new JFrame(); app.add(new Sample53a()); app.setSize(400, 300); app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); app.setVisible(true); } interface Figure { public void draw(Graphics g); } static abstract class SimpleFigure implements Figure { //5.2のものとは違っていることに注意 int xpos, ypos; public SimpleFigure(int x, int y) { xpos = x; ypos = y; } public void moveTo(int x, int y) { xpos = x; ypos = y; } public void draw(Graphics g) { g.setColor(Color.BLACK); ((Graphics2D) g).setStroke(new BasicStroke(4)); } } static class Maru extends SimpleFigure { int size; public Maru(int x, int y, int s) { super(x, y); //親クラスのコンストラクタ size = s; } public void draw(Graphics g) { super.draw(g); //親クラスのdrawメソッド g.drawOval(xpos - size, ypos - size, 2 * size, 2 * size); } } static class Batsu extends SimpleFigure { int size; public Batsu(int x, int y, int s) { super(x, y); //親クラスのコンストラクタ size = s; } public void draw(Graphics g) { super.draw(g); //親クラスのdrawメソッド g.drawLine(xpos - size, ypos - size, xpos + size, ypos + size); g.drawLine(xpos - size, ypos + size, xpos + size, ypos - size); } } static class Rect extends SimpleFigure { Color col; int width, height; public Rect(Color c, int x, int y, int w, int h) { super(x, y); //親クラスのコンストラクタ col = c; width = w; height = h; } public boolean hit(int x, int y) { return xpos - width / 2 <= x && x <= xpos + width / 2 && ypos - height / 2 <= y && y <= ypos + height / 2; } public int getX() { return xpos; } public int getY() { return ypos; } public void draw(Graphics g) { g.setColor(col); g.fillRect(xpos - width / 2, ypos - height / 2, width, height); } } static class Text extends SimpleFigure { String txt; Font fn; public Text(int x, int y, String t, Font f){ super(x,y); txt = t; fn = f; } public void setText(String t) { txt = t; } public void draw(Graphics g) { super.draw(g); g.setFont(fn); g.drawString(txt, xpos, ypos); } } }

補足:論理型変数

public boolean eq1(int x) { if(x>10) return true; else return false; } public boolean eq2(int x) { return x>10; }


ykitamura@kwansei.ac.jp