プログラミング言語論0629

プログラミング言語論
第十二回
理工学部
情報システム工学科
新田直也
オブジェクトとメッセージ



オブジェクト同士はメッセージで互いに情報をやり取りする.
オブジェクトはお互いに相手の中身を知らない.
オブジェクトの型をクラスという.
クラス
オブジェクト
(インスタンス)
メッセージ
(メソッド呼出し)
継承

継承:
基本となるクラスを拡張して,新しいクラスを定義すること.

親クラス:
元となるクラス.スーパークラスとも言う.

子クラス:
親クラスを拡張したクラス.拡張した部分だけ定義する.
基底クラス
クラスA
派生
クラスC
派生
クラスB
派生
クラスD
Javaによるオブジェクト指向
(クラス)

クラスは,メンバ変数とメソッドをカプセル化したもの.

例:
class Vector {
double x;
double y;
Vector add(Vector a) {
x += a.x;
y += a.y;
return this;
}
double inner_product(Vector a) {
return x * a.x + y * a.y;
}
double length() {
return Math.sqrt(inner_product(this));
}
}
メンバ変数
メソッド
Javaによるオブジェクト指向
(継承)

extends キーワードを使って継承する.


拡張するメンバ変数,メソッドのみ定義する.
例:
class Vector3D extends Vector {
拡張するメンバ変数
double z;
Vector add(Vector a) {
x += a.x; y += a.y; z += a.z;
置き換える
return this;
メソッド
}
double inner_product(Vector a) {
拡張する
return x * a.x + y * a.y + z * a.z;
メソッド
}
Vector3D outer_product(Vector3D a) {
return new Vector3D(y*a.z - z*a.y, z*a.x - x*a.z,
x*a.y - y*a.x);
}
}
Javaによるオブジェクト指向
(継承とメソッド呼出し)

メソッド呼出しの例:
class Test {
public static void main(String args[]) {
Vector a = new Vector(5, 10);
Vector b = new Vector(15, 20);
Vector3D c = new Vector3D(5, 10, 15);
Vector3D d = new Vector3D(20, 25, 30);
System.out.println(a.inner_product(b));
Vectorの
System.out.println(c.inner_product(d));
Vector3Dの
System.out.println(a.length());
Vectorの
System.out.println(c.length());
Vectorの
a = a.outer_product(b);
エラー!!
c = c.outer_product(d);
Vector3Dの
}
}
多態性(最も単純な例)
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();
A1
a.m();
// “this is class A1”と表示
a = new A2();
a.m();
// “this is class A2”と表示
}
}
A
派生
A2
多態性の考え方

メッセージを送る人は送り先の具体的なクラス
(具象クラス)を知らなくてもよい.

実際に呼ぶメソッドは実行時に決まる(遅延束縛).
Aa
Test
m()
m()
Aa
Aa
A
A1
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 {
void move(int x, int y) {
:
// 四角形クラス
// 移動メソッドをオーバーライド
多態性の使い方3

選択図形の移動:
// 選択図形の配列を取得(図形の具象クラスは不明)
Shape [] sel_obj = GetSelectedObjects();
// 配列中の各要素を移動する
Shape クラス for (int n = 0; n < sel_obj.length; n++) {
sel_obj[n].move(x, y);
の参照変数の
}
配列
Shape sel_obj[n]
多態性により Shape
クラスまたは子クラス
のmoveメソッドが呼
ばれる
本日の目標

多態性を使って,図形を表示するアプリケーションを
作ってみよう!!

仕様:



図形の種類は,正三角形と正方形,円の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; }
クラス変数,クラスメソッド

クラス変数:
クラスが持つ変数.全インスタンスで値を共有できる.

クラスメソッド:

インスタンスを指定せずに呼び出せるメソッド.内部ではクラ
ス変数にしかアクセスできない.
使用例:
class A {
static int MAX_NUM = 1000;
static int getMaxNum() {
return MAX_NUM;
}
n = A.getMaxNum();
修飾子のまとめ

よりオブジェクト指向らしいプログラムのために…

修飾子:

抽象メソッド,抽象クラス
abstract

アクセスレベル
public,protected,private

クラス変数,クラスメソッド
static