初めてのRuby

初めてのRuby

初めてのRuby


本書のターゲットは「プログラミングの経験はあるが、Rubyは初めて」の人です。おかげで200ページくらいの薄い本になっており、図書館で借りてきてから一気に読むことが出来ました。
Java歴6年の私のような人からすると、「変数とはデータを一時的格納する入れ物のようなもので・・・」みたいな部分はもういいよっ!ってなると思うので(笑)、純粋にRubyってどんな言語なんだろう、ということが知りたい人にオススメです。主にネットの情報を拾って勉強してきた私ですが、本書を最初に読んでいればすっきり整理された状態で臨めたと思うので、もっと学習がスムーズに進んだかなw
初心者向けの技術本は多いけど、中級者向けの本が少ないので、こういう本が増えると嬉しいです。

初めて知ったこと・忘れていたことを簡単にメモ

equal?と==
Javaは==が同一インスタンスかどうか、equalが同値がどうかを確かめるのに対し、rubyではその逆となる。

str1 = "hello"
str2 = "hello"
puts str1 == str2 # true
puts str1.equal? str2 # false


Stringはmutableオブジェクト
rubyのStringはJavaのStringと違い、mutableオブジェクトのようです。よって以下のように文字連結を行ってもインスタンスの内部状態が変わっているだけで、新たなインスタンスが生成されているわけではない。

oid = (str = "red").object_id
puts (str << "blue" << "yellow").object_id == oid  #trueとなる

ただし、以下はfalseになります。「+」だとJavaのように新しいStringオブジェクトが生成される。

oid = (str = "red").object_id
puts (str += "blue").object_id == oid  #falseとなる


ifは文ではなく式なので戻り値を持つ。

num = 2
result = if num.even?
  num+=1
else
  num+=2
end

puts result # 3


rubyではいわゆる戻り値がvoidのメソッドはない
必ず何か値を返す。何も戻り値がなさそうに見えても実際は「nil」が返る。

class Sample
  def self.hoge
    "hoge"
  end
  def self.piyo
  end
end
puts Sample.hoge # hoge
puts Sample.piyo # nil


メソッドのオーバーライドは出来ない
動的ゆえにJavaのように型や個数によってオーバーライドが簡単にできない。


多重代入のサポート
時々見かける「*」がつくヤツが何を表しているのかよく分かっていなかった。
最初の例はaに1,bに2cには3が代入され、4と5は捨てられる。一方*cとするとa,bは同じだがcには[3,4,5]の配列が代入される。これを利用して可変長引数が実現できる。

a,b,c = [1,2,3,4,5]
a,b,*c = [1,2,3,4,5]


Procオブジェクト
時々みかける「&」がつくヤツが何を表しているのかよく分かっていなかった。&をつけるとわたってきたブロックをProcオブジェクトとして扱うことが出来る。ゆえにメンバ変数に格納しておき、あとから実行といったようなことが出来る。

class Sample
  def register(&proc)
    @proc = proc
    self
  end
  def exe_with_registered_block
    @proc.call("hello", "world")
  end
  def exe_with_block
    yield("hello", "japan")
  end
end

Sample.new.exe_with_block{|a, b| puts "#{a}, #{b}"} # hello, japan
Sample.new.register{|a, b| puts "#{a}, #{b}"}.exe_with_registered_block # hello, world


メタプログラミング
rubyの特徴としてよく挙げられるんですが、ちゃんと理解していなかった。プログラミングのためのプログラミングができる。クラス定義すらプログラムで制御できる。
・・・といってもよく分からないと思うので例。このプログラムの意味は、rubyのバージョンが1.8.6より上のバージョンならParent1を継承してそうでなければParent2を継承するということ。私の環境は1.8.7なので実行するとtrueと出力される。これヤヴァイな。Javaな私には刺激が強すぎるわw

class Parent1; end
class Parent2; end
class Child < (RUBY_VERSION > "1.8.6" ? Parent1 : Parent2); end

puts Child.new.is_a? Parent1 # 1.8.6より上ならtrue

「まつもと直伝 プログラミングのオキテ 第6回 メタプログラミング」もあわせて読むといい。


特異メソッドと特異クラス
上のメタプログラミングと関係するけど、特異メソッドは特定のインスタンスへのメソッド追加だと思っていたら、実は特異クラスに対するメソッド追加だった!さらにいうと、クラスメソッドの定義というのは、Classのインスタンスに対する特異メソッド定義のことだった!!最初一読しただけではよく分からなかった。