RubyOnBasis[01] 新人Railsエンジニア向け講座

このシリーズについて

RubyOnBasisはRuby on Railsを業務に利用する新人Webエンジニアのための、Railsを使わないテキストだ。この講座ではWEBrickを使ってWebアプリを書きながらHTTPを始めとする基礎知識をキャッチアップしてRailsがどうやって作られ動くのかを理解していく。

このシリーズを始めから読む

クラスとインスタンス

最初に取り上げる話題は、そうクラスだ。一体こいつらは何なんだ?よく用いられるのが、クラスは設計図でありインスタンスは設計図を元に作られた実体だという説明だ。聞いたことがあるだろう。

実のところ、言語によってクラスの定義は様々だ。名著「コーディングを支える技術」によればクラスという言葉が使われ始めた初期においてはその単語の通り「分類(classes)」のことだった。しかしAlan KayによりSmalltalkオブジェクト指向が生み出されて以降はクラスと言えば一般には以下のような役割を持つものだ。

  1. 変数とメソッドのまとまりを作る
  2. 実行可能な処理を定義する
  3. コードを再利用するための単位

Rubyのクラスとインスタンスについて、こう表現をしてみよう。クラスはメソッド(関数)など振る舞いの情報を持つオブジェクトであり、インスタンス状態の情報を持つオブジェクトだ。 (クラス変数や特異メソッドの話はやめてくれ、物には順序があるんだ。っていうか君にはこのチャプターは必要ないよ!)

メソッドを利用する者、オブジェクト

オーケー。いきなりオブジェクトという単語が出て来たので首を傾げたかもしれない。もっとも簡単に表現すれば、オブジェクトとはメソッドを利用できるものと言える。

例えば @server.send_error_mailに出て来る@serverのようにメソッドを利用することが出来るなら、それはオブジェクトだ。オブジェクト指向パラダイムを簡単に説明するのは難しいから今日はこれだけ覚えてくれ。オブジェクトとはメソッドを利用できるものだ。

コードで学ぶクラスとインスタンス

さて、クラスとインスタンスの話へ戻ろう。クラスは振る舞いの情報を持ち、インスタンスは状態の情報を持つと説明したね。この「状態(State)を持つ(stateful)」、という概念は幅広く通用する概念なので仲良くしておこう。

では実際にコードを書いてみよう。コードが中々出てこない技術書は退屈だ。ドラクエ7はスライムと戦うまでが長過ぎるのが欠点だった。

class Article
  def set_body(text)
    @body = text
  end

  def get_body
    @body
  end
end

first_article = Article.new
first_article.set_body('ごん、おまいだったのか…')
puts first_article.get_body # @bodyが出力される

今日はブログのようなアプリを想像しながらコードを書いてみよう。Article(記事)クラスには二つのメソッドが定義されている。

set_bodyメソッドは与えられた引数をインスタンス変数@body(本文)に代入するだけのメソッドだ。get_bodyメソッドはそれよりも簡単でset_bodyメソッドで代入した@bodyをそのまま返してくれる。

インスタンス変数って何かって? 名前の通りインスタンスがそれぞれ持っている変数だ。インスタンスの中身をわかりやすく見てみようか。

インスタンスの中身を覗いてみよう

ちょっとコードを書いてみよう。もうひとつ追加でインスタンスを作り、二つのインスタンスがどんな情報を持っているかをinspectメソッドを使って表示させる。

class Article
  def set_body(text)
    @body = text
  end

  def get_body
    @body
  end
end

first_article = Article.new
first_article.set_body('ごん、おまいだったのか…')

second_article = Article.new
second_article.set_body('その声は我が友、李徴子ではないか!')

puts first_article.inspect
puts second_article.inspect
#<Article:0x007f9a421a3450 @body="ごん、おまいだったのか…">
#<Article:0x007f9a421a3400 @body="その声は我が友、李徴子ではないか!">

冒頭に書いたクラスとインスタンスの説明が少しわかってきたかな。Articleクラスはset_bodyやget_bodyといったメソッド(振る舞い)の情報を持っていて、それがどんな処理なのかを決める。

そしてfirst_article.inspectの結果からもわかるように、インスタンスインスタンス変数などの形で状態を持っている。そして、自分自身が何のクラスなのか、もね。

本当にメソッドはクラスが持っているの?

ちょっと考えるとfirst_article.get_bodyのように書けるのだからメソッドに関する情報もインスタンスが持っているように思えるかもしれない。よく知らないけどインスタンスを作った時にクラスからコピーでもしておくんじゃないの??ってね。でもそれは間違いなんだ。

rubyの処理系がfirst_article.get_bodyという記述を見つけたとき、まず処理系はfirst_articleが何のクラスなのかを調べる。Articleクラスらしいぞ? じゃあArticleクラスがget_bodyメソッドを定義しているか調べよう。オーケイ、どんな処理をすればいいかわかったよ…とこういう具合だ。

本当かな…確かめてみよっか? Rubyオープンクラスという仕組みを採用しているから、既に定義されたクラスへメソッドを追加したり修正したり削除したり出来る。いつでも好きなタイミングにね。この仕組みを使ってインスタンスを作った後でメソッドの処理を書き換えてイタズラしてみよう!

class Article
  def set_body(text)
    @body = text
  end

  def get_body
    @body
  end
end

first_article = Article.new
first_article.set_body('ごん、おまいだったのか…')
puts first_article.get_body

class Article
  def get_body
    "にゃーん!"
  end
end

puts first_article.get_body
ごん、おまいだったのか…
にゃーん!

クラスのメソッド定義を上書きして@bodyの代わりに文字列"にゃーん!"を返すようにした。実行してみると見事に puts first_article.get_body の結果が変わったね。ちなみに、こうやって同名のメソッド名で既存のメソッドを上書きすることをオーバーライド(override)なんて風に呼ぶんだ。

参考文献

  • 『コーディングを支える技術』西尾泰和

<< 前のチャプターへ戻る | 次のチャプターへ進む >>