ブラックジャックのプログラムを、Cardクラスを利用するように変えたこと で、データ構造の修正がしやすくなるとともに、ブラックジャック以外のカード ゲームを作るときの労力が削減できることは想像できただろうか。
オブジェクト指向の考え方の入口に進むために、 実際にクラスを設計していく場合の基本的な考え方を見ていこう。
クラス定義は class
文によって行なう。
class クラス名 〜〜定義本体〜〜 end
定義したクラスには、プログラミングのときに利用したい対象物の 持つ内部情報や、必要な処理手順を埋め込んでいく。たとえば、トランプゲーム を作るときには、トランプのカードそのものが必要となる。これに必要な 52(または 53)枚のカードのデータを変数として、 シャッフル処理・1枚ずつ配る処理などをメソッドとして定義する。 これらは既に作成したとおりである。
定義したクラスを利用する場合には、クラス名の後に .new
を付けて新規に生成する。生成されたもののことをそのクラスのインスタンス
という(インスタンスは「実体」の意味)。
配列を思い浮かべよう。Array
クラスのインスタンスを
Array.new
で生成すれば、そこに自由な配列データを代入していけた。
それと同様、カードを表す Card
クラスを定義して、Card.new
によって生成されたものは1組のトランプカードセットとして使えるようになる。
クラスの中で定義したメソッドは、原則としてそのクラスのインスタンスからしか 利用できない。たとえば、
class Card def next() ... end end
として、Card
クラス内にnext
メソッドを
定義した場合は、
x = Card.new x.next
のように、Card
クラスの値であるx
から
next
メソッドを呼ぶことになる。
実用的なプログラミングでは、日常にあるものを計算機上で表現する 場合が多い。そのようなときに、実際に対象物を取り扱うのに必要な典型的な 手順がいくつか考えられるような場合、それはクラス定義にするとよい。
たとえば、五目並べゲームを作る場合、必要なのは碁盤と碁石のセットである。 それをRubyの変数でどのように表現するか、また、石を置いたりするときに 変数をどう変更するかを考える。これをできるだけ抽象的にしておいて、 五目並べを作るときにも、囲碁を作るときにも利用できるようにする ことを目標にする。たとえば、碁盤と碁石の場合、考えられる処理は 以下のようになるだろう。
new
)
他にもあるかもしれないが、この程度の処理を考えておけば碁盤を利用する
色々なゲームで利用できそうである。ということで、碁盤を実現する
Goban
クラスを考えると以下のような骨組になる。
class Goban def initialize() # newされたときに自動的に呼ばれる # 碁盤を初期化する # 盤面を配列とかで作ったりする # 黒石、白石の個数を保存する変数を初期化したりする end def putBlack(x, y) # 座標 (x, y) に黒を置くメソッド # 黒石の残り数を1減らしたりするといいかもね # 置ける場合は残りの打点数を、置けない場合は false を返す。 end def putWhite(x, y) # 座標 (x, y) に白を置くメソッド # 白石の残り数を1減らしたりするといいかもね # 置ける場合は残りの打点数を、置けない場合は false を返す。 end def remove(x, y) # 座標 (x, y) の石を取り除くメソッド # 取り除いたのが黒か白かに応じて残り数を復活させる end def at(x, y) # 座標 (x, y) に何があるかを返す # "白" か "黒" か nil か、かな(nilは何もない) end def displayGoban() # 現在の盤面を画面表示するメソッド # forとかwhileで表示するんだろうね end def reset # 全ての盤面情報をリセットして # 黒石、白石の個数を保存する変数を初期化したりする end end
これを使うと、五目並べゲームは
board = Goban.new while true print "どこに打ちますか? (x, y): " line = gets.chomp! if /(\w), *(\d)/ =~ line # A, 5 とか入れてもらうはず x, y = $1, $2 # x="A", y="3" とかになるはず else redo end if !board.putBlack(x, y) # 人間の手を置く puts "そこには置けないよ!" redo end if check5(board) # 5目並んでるか調べるメソッド puts "あなたの勝ちです!" break end x, y = thinkComputer(board) # COM思考ルーチン(難しいのでまだ無理ね!) board.putWhite(x, y) # コンピュータの手を置く if check5(board) # 5目並んでるか調べるメソッド puts "わたしの勝ちです!" break end end
というような流れで作ることができるだろう。もちろん、プログラムの
中に登場する未知のメソッドは自分で作らなければならず、それはかなり
難しいものになるだろう。しかし、Goban
クラスを定義して、
それを利用したプログラムにすることで、碁盤を配列で表現しても
ハッシュで表現しても、通し番号で表現しても、あるいはもっと
すばらしい内部構造で表現しても、五目並べのゲーム進行部分は
一切修正せずに済むことになる。さらには、囲碁プログラムを作る場合にも
同じクラス定義を利用でき大幅な作業量削減につながる。
Rubyでのクラス定義に関しては以下の決まりがある。
new
によってクラスの実体(インスタンス)
が1つ生成される
@
記号で始まる変数を利用すると、
クラスのインスタンス内のみで有効なものになる
initialize
という名前のメソッドは
インスタンスが生成されるときに必ず呼ばれるので、このメソッドで
必要な初期化を行なう
メソッド名
という名前で定義する。クラスメソッドは、プログラムの
任意の箇所で利用することができる。
クラス定義、に代表されるオブジェクト指向の考え方は、現在では 本格的なプログラミングを行なうときには必須となってくるものである。 その考え方を深く学びたい場合は、Ruby言語、またはJava言語を深く学習すると よい。 オブジェクト指向そのものを解説する書籍はJava言語を対象とした もののほうが豊富だろう。