Chapter.01 Hello, ruby.
2017-10-02
クラスとインスタンス
最初に取り上げる話題は、そうクラスだ。一体こいつらは何なんだ?よく用いられるのが、クラスは設計図でありインスタンスは設計図を元に作られた実体だという説明だ。聞いたことがあるだろう。
実のところ、言語によってクラスの定義は様々だ。名著「コーディングを支える技術」によればクラスという言葉が使われ始めた初期においてはその単語の通り「分類(classes)」のことだった。しかしAlan KayによりSmalltalkやオブジェクト指向が生み出されて以降はクラスと言えば一般には以下のような役割を持つものだ。
- 変数とメソッドのまとまりを作る
- 実行可能な処理を定義する
- コードを再利用するための単位
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)なんて風に呼ぶんだ。
参考文献
- 『コーディングを支える技術』西尾泰和

[82]