Rubyのクラス階層には、30を超える組み込みクラスがあらかじめ定義されている。
他の多くのオブジェクト指向言語と同様に、Rubyは多重継承を許さない。
しかしながら、必ずしも機能が制限されるわけではない。
現代のオブジェクト指向言語は、たいてい単純継承モデルに従っている。
次のセクションで説明するように、RubyではモジュールとMix-inがサポートされている。
また、RubyにはオブジェクトIDも実装されている。
オブジェクトIDは永続的で分散型で再配置可能なオブジェクトの実装をサポートする。
既存のクラスからオブジェクトを生成する場合、通常は次の用にnewメソッドを利用する
myFile = File.new("hoge.txt","w") myString = String.new("This is a String Obj")
ただし、次に示すように、これは必ずしも必要ではない。
yourString = "This is also a string obj" aNumber = 5
変数はオブジェクトへの参照(アドレス値)を格納する為に利用される。
前述の様に、変数自体は型を持たないし、オブジェクトの実態でもない。
オブジェクトの実態は別に存在し、変数はその参照(アドレス値)を持っているにすぎない。
ただし、Fixnumなど、一部の組み込みクラスの小さな不変オブジェクトは例外となっており、参照元の変数に直接コピーされる。
※これらのオブジェクトはせいぜいポインタ並の大きさなので効率的だと考えるらしい。
この場合、代入によってオブジェクトのコピーが作成されるため、ヒープ(メモリ割り当て領域)は利用しない。
オブジェクトには型がある。
x = "abc"
変数の代入によって、次の用にオブジェクト参照が共有される。
y = "abc" x = y p x #=> "abc"
x = yが実行された後、変数xと変数yは同じオブジェクト(アドレス)を参照している。
puts y.id #=> 53732208 puts x.id #=> 53732208
オブジェクトが可変の場合は、一方の変数を変更すると、次の用にもう一方の変数にそれが反映される。
x.gsub!(/a/,"x") # "abc"のaをxに変更する。!付きのgsubなので対象を破壊的に変更 puts y # yが指し示しているオブジェクトとxが指し示しているオブジェクトは同じなので"xbc"になっている
可変オブジェクトを不変オブジェクトに変更する為には、freezeメソッドを利用する。
x.freeze x.gsub!(/b/,"y") # => 書き換えられないのでエラーになる
Rubyのシンボルは、変数を参照しているものを指し示す物ではなく、変数のID自体を指している物である。
:hogeのようにコロンをつけるとシンボルになる。
その識別子がまだ存在していない場合は、新たに作成される。
シンボルには様々な使い方があるが、とりわけ識別子を利用するのではなく言及したいときに利用する。
つまり、識別子を使うことで、「識別子が指している物」と「識別子それ自身を知りたい時」の違いである。
これは、C言語のenumに近い。
irb(main):001:0> "abc" == "abc" => true irb(main):002:0> "abc".equal?("abc") => false irb(main):003:0> :abc == :abc => true irb(main):004:0> :abc.equal?(:abc) => true
== は表現を比較し、equal? はオブジェクトの同一性を比較する。
文字列は同じ表現が同一の実体とは限らないが同じ名前のシンボルは同じ実体である。
Ruby でシンボルが使われる典型的な例はハッシュのキーである。
irb(main):010:0> {:key1 => "one", :key2 => "two"} => {:key1=>"one", :key2=>"two"}
シンボルは文字列を数値にコンパイルする。
内部的には整数になっている。
整数になっていると言うことは、比較処理を行うときは文字列よりも処理スピードが早くなる。
これはつまり、a=12345;b=67890のときのa==bと、a="abcde";b="fghij"のときのa==bとで前者であるa=12345;b=67890の方が速い。