オブジェクト指向プログラミング

Java言語の1番の特徴です.
実際に何かの装置を組み立ててゆく感覚でアプリケーションプログラムを作り上げる開発スタイルが
「オブジェクト指向プログラミング」です.

導入  応用例:スタック  応用例:リスト


■ 導入

オブジェクト指向プログラミングというものを理解するためのたとえ話をします.

実物の機械装置は複数の部品から構成されており,装置全体の動作は,
装置を構成する部品たちの動作が織りなすものです.

オブジェクト指向プログラミング(以下OOPと略します)の考え方が生まれる以前は,
コンピュータのプログラムは「開始から終了までの処理の流れ」という解釈をするだけでした.

OOPのスタイルによるプログラム開発では「ある動作をする部品」たちを組み合わせて,
全体として1つの装置を作り上げるような形でシステムを作り上げます.

つまりOOPでは,アプリケーションプログラムの開発は主に
 ● 部品の構造の定義の記述
 ● 部品の動作の記述
の2つを行うことになります.

以下では,プログラム例を見ながらOOPについて説明します.


ページトップへ↑

■ 応用例: スタック

「データ構造(基本)」のページで説明したスタックのシステムを,OOPのスタイルで実際に
つくってみます.

開発の基本は,上で説明した「部品の定義」と「部品の動作」の2つです.

それではまず「部品の定義」からはじめましょう.

OOPでは,何かの実体を「クラス」(class)という考え方で扱います.
つまり何かの「部品」を定義する際も,その部品を表すクラスの定義をするわけです.

クラスの定義   class  クラス名  { 定義内容 }
    "定義内容" で記述されるクラスを "クラス名" という名前で新たに定義する.

"定義内容" に記述するものは主に,「そのクラスがどんな部分をもつのか」と,
「どのような動作をするのか」の2種類です.

クラスを構成する各部分を「メンバ」といいます.また,そのクラスのオブジェクトがとる
動作を「メソッド」といいます.すなわちクラスの定義は主に,メンバの列挙とメソッドの記述に
なります.

メンバの定義:

ではスタックをつくるために必要なメンバを定義しましょう.

今回は,文字列のデータを蓄積するスタックをつくることにします.

複数の文字列データを積み上げてゆくので,文字列の配列("String[ ]"の型)を用意します.
あと,現在のスタック位置を示す「ポインタ」とそれが取り得る最大値を記録する変数が必要で,
それらは整数の変数("int"の型)とします.

下のプログラムを見てください.

スタックのクラス "MyStack" の定義  class MyStack {
    String[ ]  memory;
    int     p, max;
  }

このように記述することで,"memory", "p", "max" というメンバを部品として持つ装置
の設計図が,クラス "MyStack" としてできたことになります.

次にこのクラスのメソッドを定義することで,「装置の挙動」を決めましょう.

メソッドの定義:

メソッドは,
  "メソッド名( 引数の記述 ) { 動作の記述 }"
という形で記述します.例えば,スタックを初期化するメソッドは次のように記述します.

  MyStack( int m ) {
    memory = new String[ m ];
    max = m - 1;
    p = -1;
  }

「初期化」ですから,まず複数の文字列を格納する配列を new で生成しています.
このときの配列のサイズは m で与えられるものとして,実際にこの初期化メソッドを実行する際には,
m には具体的な数値が与えられます.

つまり「サイズが m のスタックを設置する」というわけです.

配列は 0 から始まるので,スタックの場所を示すポインタの最大値は m - 1 になるので
その値が max にセットされています.

そして,スタックは出来上がった最初の状態ではデータが入っていないので,ポインタは -1
としておいて「空」である状態にしておきます.

以上が「初期化」を実行するメソッドの記述です.

スタックには,データを新規に与える "push" の動作と,データを取り出す "pop" の動作があり,
それらもメソッドとして記述します.(下記参照)

● push動作のためのメソッド
  public void push( String d ) {
    p++;
    memory[ p ] = d;
  }

このメソッドは d という変数に与えられた文字列を push するものです.ポインタを1つ上げて,
配列 memory に d が持つ文字列をセットしています.

● pop動作のためのメソッド
  public String pop( ) {
    r = memory[ p ];
    p--;
    return( r );
  }

このメソッドはポインタが示す位置の配列の要素を r という変数に与え,それを返すものです.
もちろん pop したあとはその要素がスタックから消滅するので,ポインタを1つ下げています.

さて,そろそろ理解しにくくなってきたと思います.

「今,何をやっているのか?」

コンピュータのプログラムというものは,処理の手順を書き並べるもののはずですが,
宣言したり定義したりと,動く部分が見えませんね.

さてここで,完成したスタックプログラムを眺めて見ましょう.次の "StackTest.java" を
眺めてください.

プログラム:StackTest.java
//スタックの定義
class MyStack {
	//記憶域,スタックポインタ,最大値
	String[ ] memory;
	int p, max;
	String r;
	//初期化
	MyStack(int m) {
		memory = new String[m];
		max = m - 1;
		p = -1;
		System.out.print(m+"の大きさのスタックを確保し,");
		System.out.println("スタックポインタを初期化しました.");
	}
	//push
	public void push(String d) {
		if ( p < max ) {
			p++;
			memory[p] = d;
			System.out.println(p+"番目に"+d+"をpushしました.");
		} else {
			System.out.println("スタックオーバーフロー!(失敗)");
		}
	}
	//pop
	public String pop() {
		if ( p >= 0 ) {
			r = memory[p];
			System.out.println(p+"番目のデータをpopします.: "+r);
			p--;
		} else {
			r = "";
			System.out.println("スタックは空です!(失敗)");
		}
		return(r);
	}
}

//スタックのテスト
class StackTest {
	public static void main( String argv[] ) {
		MyStack stk;
		stk = new MyStack(8);
		stk.push("a");
		stk.push("b");
		stk.push("c");
		stk.pop();
		stk.pop();
		stk.pop();
		stk.push("d");
		stk.push("e");
		stk.push("f");
		stk.pop();
		stk.pop();
		stk.pop();
		stk.pop();
	}
}

"//スタックの定義" からはじまる前半部と,"//スタックのテスト" からはじまる後半部に分かれています.

ところで "//" という記述があると,そこから行末まではただの「コメント文」となり,プログラムとは
みなされなくなります.プログラム中に何かをメモ書きする場合に使う方法です.

それで,前半部分は何をやっているかというと,「スタックシステム」の設計図を書いているだけです.
この部分だけでは,何の動作もありません.

実際にに「動く」プログラムは後半の "StackTest" というクラスの中の main メソッドです.

(構築中)


ページトップへ↑

■ 応用例: リスト

(構築中)