クラス定義

ブラックジャックのプログラムを、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の変数でどのように表現するか、また、石を置いたりするときに 変数をどう変更するかを考える。これをできるだけ抽象的にしておいて、 五目並べを作るときにも、囲碁を作るときにも利用できるようにする ことを目標にする。たとえば、碁盤と碁石の場合、考えられる処理は 以下のようになるだろう。

他にもあるかもしれないが、この程度の処理を考えておけば碁盤を利用する 色々なゲームで利用できそうである。ということで、碁盤を実現する 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におけるクラス定義

Rubyでのクラス定義に関しては以下の決まりがある。

結局クラス定義って…?

クラス定義、に代表されるオブジェクト指向の考え方は、現在では 本格的なプログラミングを行なうときには必須となってくるものである。 その考え方を深く学びたい場合は、Ruby言語、またはJava言語を深く学習すると よい。 オブジェクト指向そのものを解説する書籍はJava言語を対象とした もののほうが豊富だろう。


本日の目次