旧gaaamiiのブログ

間違ったことを書いている時があります。コメントやTwitter、ブコメなどでご指摘ください

Rubyのirbでなんとなく「クラス」とか「メソッド」とかに触れる

追記:なんか後になって読み返してみたら、オブジェクト指向の説明として全く適切じゃないように思えてきました。ただ、プログラミング初めてみたけど何がなんだかよくわからんというレベルの人(この記事を書いた時の僕くらいの人)がRubyのクラスやらメソッドやらを初めて扱う上でこういう記事があってもいいんじゃないかなと思ってタイトルを変えて残しています(変更前はオブジェクト指向入門みたいな記事タイトルでした)。

ソフトウェア設計としてしっかりとオブジェクト指向を学びたい人には、オブジェクト指向のこころ (SOFTWARE PATTERNS SERIES)という本がおすすめです。


最近、オブジェクト指向をどう教えればいいのかという記事をよく目にします。僕も昨年の今頃はオブジェクト指向なんてさっぱりだったし未だにちゃんと理解しているか怪しいくらいなのですが、自分の理解のために一度こういう文章にしておきたいなと思い立ち、この記事を書いています。

まず前提として、この記事が目指すのは確実な理解とか完璧な定義ではありません。この記事は、オブジェクト指向になんとなく触れて感触を確かめるためのものです。

また、今回はRubyが使える環境がある前提で書いてしまったため本当に初心者向けと言えるのかな...という不安があります。irb使えれば入門は果たせるかもしれないけど、irb使える環境が無いとこの記事は読んでも無駄になるかもしれません。 コメントやTwitterで「Rubyどうやったら使えるのさ」という声があれば、初心者がすぐに使える環境も紹介したいと思います。

オブジェクト指向はなんでわかりづらいのか

なんでオブジェクト指向はわかりづらいのかというと、抽象化しすぎだからではないかと思います。たい焼きの説明は話としてはとてもわかりやすいけれども、問題はプログラミングでたい焼きを作る場面が無いということです。たい焼きはたい焼き器やあんこで作るものです。

実際のところプログラミングで扱うのはたいてい数値と文字列なので、素直にそれらを扱った方が親切じゃないでしょうか。そこで、文字列や数値もオブジェクトの一種として扱われるRubyオブジェクト指向を学ぶ上で最適だと思います。

文字列クラスで学ぶオブジェクト指向

Rubyにおいて、文字列はオブジェクトです。クラスがあり、インスタンスが作れます。と、この意味がわからない人のためにirbを使って解説します。irbを立ち上げてください。ターミナルでirbと打てば使えるはずです。

以下では、基本的に一緒に試してもらいながら読んでもらうのを想定しています。ただ読むだけではわからないかと思いますので、まずはirbを立ち上げましょう。

文字列の正体

irbを立ち上げたら、こうしましょう。

hoge = "ほげ"

うん、変数に文字列を代入しただけっぽいです。ではこのhogeの正体を探るとこから始めます。hogeの正体を知るにはhoge自身が持ってるメソッドから選ぶのがいいでしょう。以下の様にhogeが持ってるメソッドを尋ねます。

hoge.methods

いろいろ返ってきましたね。hogeの正体を知るには、クラスを尋ねるためのclassメソッドを使います。

hoge.class

Stringと返ってきました。ここから、「hogeはStringクラスのインスタンスだ」ということが言えます。文字列の正体はStringクラスのインスタンスだったのです。

クラスとは?

ここで、クラスの説明をします。クラスとは、設計書です。Stringでいうと、大文字にするためのメソッドとか数字を整数オブジェクトに変換するメソッドが書かれていたりします。そのおかげで、以下の様なことができるわけです。

hoge.upcase # 大文字にした文字列を返す1”.to_i # 整数オブジェクトにして返す

上のように、メソッドはオブジェクト.メソッドという記法で使えます。上からわかるように、hogeの中身は"ほげ"という文字列であると共に、いろいろと小便利なメソッドを持った実体だと言えそうです。

インスタンスとは?

インスタンスとはクラスという設計書を元に作られた実体を指します。つまり、hogeのことです。実体っぽさをつかむには、それぞれがちゃんとアイデンティティを持っていることを確認しましょう。

hoge1 = “ほげ”
hoge.object_id

hoge2 = “ほげ”
hoge2.object_id

object_idというメソッドを使うことで、オブジェクトのIDを返してもらえます。ちゃんと違う数値が返ってきたはずです。入ってる文字列は同じでも、違う実体だということがわかりましたね。

文字列クラスを自分で設計してみる

次に、クラスをどう作るのかというのを体験するために自分なりに工夫して一風変わった文字列クラスを実装してみます。

  • 4文字に略したものを返すメソッド
  • 語尾に「ぽよ」を付けて返すメソッド
  • 語頭に「マジで」を付けて返すメソッド

では早速、テキストエディタを開いて以下のコードを書いてMyClass.rbのようなてきとーなファイル名で保存しましょう。

class MyString

  def initialize(s)
    @string = s 
  end 

  def abbreviate
    @string[0] + @string[1] + @string[@string.size / 2] + @string[(@string.size / 2) + 1]
  end 

  def poyonize
    @string + "ぽよ"
  end 

  def majide
    “マジで” + @string
  end 

end

s = MyString.new("愛のままにわがままに僕は君だけを傷つけない")
puts s.abbreviate
puts s.poyonize
puts s.majide

書いたコードは、

ruby MyClass.rb

で実行できます。

なんだかセンスが無いメソッドですが、まあふんわりつかんでもらえたら幸いです。これをもとにもう少し説明を続けます。

コンストラクタとは?

ここで何気なく登場したのが、initializeメソッドです。これはMyString.newのようにインスタンスを作るときに実行されるメソッドで、一般的にはコンストラクタと呼ばれたりします。

MyString.new(“愛のままにわがままに僕は君だけを傷つけない”)

とすることで、@stringというインスタンス変数に文字列を代入しています。

インスタンス変数とは?

インスタンス変数とは、その名の通りインスタンスが持つ変数です。今回は、この@stringというインスタンス変数に入れたものに「ぽよ」とか「マジで」を付け加えたものを返すメソッドを書きました。全く実用的じゃなくて申し訳ありません。

インスタンスが持つ変数」という表現ではよくわからないという場合には、これまた実際に中身を確認してみましょう。先ほどのコードに、以下の一行を追加して実行してみましょう。

p s

pはオブジェクトをそのまま出力するためのメソッドです。ここではsに入れたMyStringのインスタンスをそのまま出力されます。

すると、MyStringというクラスのインスタンスの@stringというインスタンス変数に文字列が入っているのがわかりますね。

継承

さらにもう少し、個性的な文字列クラスを設計してみます。先ほどのMyStringとは別に、HyperStringというクラスをつくってみましょう。

class MyString

  def initialize(s)
    @string = s 
  end 

  def abbreviate
    @string[0] + @string[1] + @string[@string.size / 2] + @string[(@string.size / 2) + 1]
  end 

  def poyonize
    @string + "ぽよ"
  end 

  def majide
    "マジで" + @string
  end 

end

class HyperString < MyString

  def mitsuonize
    @string + "なあ。みつを"
  end 

  def funassize
    @string + "なっしー!!"
  end 

end

s = HyperString.new("愛のままにわがままに僕は君だけを傷つけない")
puts s.abbreviate
puts s.poyonize
puts s.majide
puts s.mitsuonize
puts s.funassize

語尾に何かつけるだけなので若干飽きてきたかもしれませんが…。 新しいクラスHyperStringのインスタンスに、先ほどのMyStringのメソッドを使うために継承を使っています。継承をするには、クラスの定義を以下のように書きます。

class HyperString < MyString
end

簡単ですね。「<」という記号は矢印だと思って大丈夫だと思います。Rubyはこういった直感的にわかりやすいシンタックスが多いのが特徴です。他の言語だと「<」ではなく「extends」と書いたりします。

まとめ

Rubyを通してクラスとインスタンス、コンストラクタ、継承といった基本的な概念に触れてきました。

僕はアホなので、オブジェクト指向についてわかりやすい説明をしてもらったりしても全然理解できませんでした。なんとなく「そういうことか」と感じたのは、手を動かしている時、パーフェクトRubyに書いてあることをirbで確認している時でした。

今回の記事はできるだけ初心者にわかりやすく書いたつもりですが、やはり手を動かさないと何にも面白くならないと思います。この記事を読みながら「語尾を相田みつをさんぽくして何が面白いんだ」と感じて自分なりにメソッドをアレンジした時にクラス設計が楽しくなるのではと思います。

参考書籍

一応、僕が読んだ本を載せておきます。

概念だけじゃなくて、オブジェクト指向に至るまでのプログラム設計手法の変遷がわかる一冊。

Rubyで遊びながらプログラミングの初歩に触れる。オタクっぽい文章が特徴的。

Rubyプログラミングのバイブルとも言える本。分厚い。