Rubyのコードを目にすると、 他の言語と似た部分があることに気が付くはずです。 構文の多くは、(他の言語の中でも特に)PerlやPython、 Javaプログラマーにとって馴染みのあるものになっています。 もしあなたがそうした言語に慣れ親しんでいるのなら、 Rubyを学ぶのはおそらくどうってことないはずです。
このドキュメントは2部構成になっています。 このページでは、プログラミング言語XからRubyへ移ってくる際に役立つ情報をざっと紹介します。 個別のページでは、Rubyの主な言語機能を紹介しつつ、 あなたが慣れ親しんできた言語との比較を行います。
求められていること: 言語XからRubyへ
重要な言語機能と知っておくべきこと
ここでは、Rubyを学習する中で出会ういくつかの主要な機能について、 参照先やヒントを示します。
イテレーション
Rubyの特徴であるブロックとイテレータは、
これまでにあまり見たことがない、あるいは使い慣れていないものかもしれません。
(CやC++、1.5以前のJavaのような)インデックスを使った繰り返し処理や、
(Perlのfor (@a) {...}
やPythonのfor i in aList: ...
のような)
リストをループする処理の代わりに、
Rubyでは次のようなコードをよく見ることになるでしょう。
each
(やcollect
、find
、inject
、sort
など)について詳しくは、
ri Enumerable
を参照してみてください(そして、次に
ri Enumerable#some_method
として具体的なメソッドを参照してみてください)。
すべては値
式と文に違いはありません。
すべては値を持ちます。nil
であっても例外ではありません。
Rubyでは次のように書くことが可能です。
シンボルは軽量文字列ではない
多くのRuby初学者はシンボルが何であるか、どう使えばよいのかを理解するのに苦戦します。
シンボルは識別子として記述するのに適しています。
シンボルは、どんな物かではなく、何者であるかがすべてです。
irb
を立ち上げて、次の違いを見てみてください。
object_id
メソッドはオブジェクトのIDを返します。
もし二つのオブジェクトが同じobject_id
を持っていれば、
それらはメモリ上の同じ実体を指すものであると言えます。
上記で見たとおり、一度でもシンボルを使ったなら、
同じ文字からなるシンボルは、いずれもメモリ内の同じオブジェクトを参照します。
同じ文字で表された2つのシンボルは、同じobject_id
を指します。
次に文字列(“george”)の方を見てみましょう。
object_id
は一致していません。
これは、二つの文字列が異なる実体を指していることを示しています。
新しい文字列を使うと、Rubyは毎回その文字列のために新しいメモリ領域を確保します。
シンボルを使うか文字列を使うかで迷ったなら、 ハッシュのキーのようにオブジェクトを識別したいのか、 それとも前述の”george”などのようにコンテンツを表したいのかを、 選択の指針にしてください。
すべてはオブジェクト
「すべてはオブジェクト」は誇張ではありません。 クラスや整数でさえオブジェクトです。 他のオブジェクトと同じように扱うことができます。
可変な定数
定数は厳密な意味での定数ではありません。 初期化済みの定数を変更したとしても、 警告はされますが、プログラムは停止しません。 だからと言って、定数を再定義するべきだということではありません。
名前付けの規約
Rubyにはいくつか名前付けについての規約があります。
大文字から始まる識別子は定数です。
ドルマーク($
)から始まる識別子はグローバル変数、
@
から始まる識別子はインスタンス変数、
@@
から始まる識別子はクラス変数になります。
メソッド名は大文字から始めることもできます。 けれど、それは次のような混乱を招くことになるでしょう。
こうすると、Constant
は10ですが、Constant()
は11になります。
キーワード引数
メソッドはRuby 2.0から、Pythonのように、 キーワード引数を定義できるようになりました。
普遍の真理
Rubyでは、nil
とfalse
を除くすべてのものは真と評価されます。
CやPythonを始めとする多くの言語では、0あるいはその他の値、空のリストなどは
偽と評価されます。次に示すPythonコードをみてください
(他の言語でもだいたい同じようなコードになるでしょう)。
このコードを実行すると「0 is false」と出力されます。 同じコードをRubyで書くと以下のようになります。
このコードを実行すると、 「0 is true」が出力されることになります。
アクセス修飾子はスコープの最後まで適用される
次のRubyコードを見てください。
another_method
がpublicメソッドになることを期待するかもしれませんが、
結果はそうなりません。
private
アクセス修飾子はスコープの終わりか、他のアクセス修飾子が
あらわれるまで継続されます。
デフォルトでは、メソッドはpublicになります。
public
、private
、protected
は実際にはメソッドになるので、
引数を受けることができます。これらにシンボルを渡した場合には、
そのメソッドの可視性が変更されます。
アクセス制御
Javaでは、public
は誰でもアクセスできることを意味しています。
そして、protected
はクラスおよび継承関係にあるクラスのインスタンス、
クラスと同じパッケージにあるクラスのインスタンスからアクセスできること、
private
はクラスのインスタンスからのみアクセスできることを、
ぞれぞれ意味します。
Rubyでは扱いが若干異なります。
public
はそのままの意味になります。
private
は、レシーバなしで呼び出すことができる場合に、
そのメソッドへアクセス可能となります。
つまり、self
のみがprivateメソッドを呼び出す際のレシーバとなります。
protected
は気をつけて扱う必要があります。
protectedメソッドはクラスか継承関係にあるクラスのインスタンスからのみ
呼び出すことができます。しかしまた、
レシーバとしてインスタンスを指定しても呼び出すことができてしまいます。
以下に例を示します(The Ruby Language FAQから引用)。
クラスは開いている
Rubyのクラスは開いています。
いつでもクラスを開いて、定義を足したり、変更することができます。
Integer
や、すべてのオブジェクトの祖先であるObject
のようなクラスであっても、
自由に再定義することが可能です。Ruby on Railsは、次のような
Integer
に時間を扱うメソッド群を定義しています。
不思議なメソッド名
Rubyでは、メソッド名の最後に疑問符(?)や感嘆符(!)が使われることがあります。
慣習的に、問い合わせ系のメソッドの最後には疑問符が使われます
(例: レシーバが空の場合にtrue
を返すArray#empty?
)。
また、使用に危険を伴うメソッドの最後には感嘆符が使われます
(例: self
あるいは引数の内容を書き換えるようなメソッド。exit!
など)。
けれど、危険なメソッドすべてがこの慣習に従っているわけでも
ないことに注意してください。
Array#replace
は、与えられた配列の内容で配列の内容を置き換えます。
この操作は、自身を変更しないようなメソッド名とは意に反する振る舞いをします。
特異メソッド
特異メソッドはオブジェクト単位のメソッドです。 特異メソッドは、定義したオブジェクトからだけ利用できるメソッドになります。
「存在しなかった」メソッド
Rubyはメッセージに対応するメソッドを見つけられなかったとしても諦めません。
その場合は、見つけられなかったメソッド名と引数と共に、
method_missing
メソッドを呼び出します。
method_missing
メソッドはデフォルトではNameError例外を投げますが、
アプリケーションに合うように再定義することもできます。
実際、多くのライブラリがそのようにしています。
以下がその例です。
このコードは単に呼び出されたメソッドの詳細を出力しているだけですが、 ここには何を書いても良いので、メッセージを受け取って適切な処理を行えます。
関数呼び出しではなくメッセージ送信
メソッド呼び出しは実際には他のオブジェクトへのメッセージ送信です。
ブロックは作りかけのオブジェクト
ブロック(実際にはクロージャ)は標準ライブラリでもすごく使われています。
ブロックを呼び出すには、yield
を使うか、引数リストに特別な引数を追加して
それをProc
オブジェクトにします。以下がその例です。
Proc.new
にブロックを渡すか、lambda
メソッドを呼び出すことで、
メソッド呼び出しの外側でブロックを作成することもできます。
同様に、メソッドもまた作りかけのオブジェクトです。
演算子は糖衣構文(シンタックスシュガー)
Rubyにおけるほとんどの演算子は糖衣構文です。
いくつかの優先順位規則にもとづいて、メソッド呼び出しを単に書き換えているだけです。
たとえば、Integerクラスの+
メソッドを次のようにオーバーライドすることもできます。
C++のoperator+
などは必要ありません。
[]
や[]=
といったメソッドを定義すれば、配列のようなスタイルでアクセスすることもできます。
(+1や-2みたいな)単項の+や-を定義するには、+@
か-@
といったメソッドを定義する必要があります。
けれど、以下の演算子は糖衣構文ではありません。
これらはメソッドではないので、再定義できません。
加えて+=
、*=
などはvar = var + other_var
、var = var * other_var
などの処理の略記法になり、これらも再定義できません。
もっと知りたい
Rubyについてもっと知りたくなったのなら、 ドキュメントの その他のコンテンツを見てみてください。