背景
社内でオブジェクト指向を教えている時、以下は同じ意味ということをインターン生に教えた。
s = ''
s = String.new
しかしIntegerクラスに対して上記と同じことを試したら例外が返ってきた。
Integer.new
#=> NoMethodError: undefined method `new' for Integer:Class
なぜか。
前提知識
- Rubyにおけるオブジェクトは、特異メソッドである
new
を使用することで生成することができる - Rubyにおいてnewでオブジェクトが生成されるクラスとされないクラスが存在する
- オブジェクトにはそれぞれ
object_id (=参照するメモリ)
を持っている
newを実行するとオブジェクトが生成できるRubyクラス
String
String.new
#=> ''
Array
Array.new
#=> []
Hash
Hash.new
#=> {}
newを実行すると例外が返ってくるRubyクラス
Integer
Integer.new
#=> NoMethodError: undefined method `new' for Integer:Class
Float
Float.new
#=> NoMethodError: undefined method `new' for Float:Class
TrueClass / FalseClass
TrueClass.new
#=> NoMethodError: undefined method `new' for TrueClass:Class
Symbol
Symbol.new
#=> NoMethodError: undefined method `new' for Symbol:Class
オブジェクトはそれぞれ object_id
を持っている
Stringの場合
同じ文字列だが、object_idは異なる値が返ってくる
s = 'test'
p = 'test'
s.object_id
#=> 70189307859540
p.object_id
#=> 70189307841860
Integerの場合
同じ数値かつ同一のobject_idが返ってくる
s = 1
t = 1
s.object_id
#=> 3
t.object_id
#=> 3
まとめ
- newを実行すると例外が返ってくるRubyクラスのオブジェクトは、1つしか持つことができない。だからobject_idが同一になり、newメソッドを使用することができない。
- 逆に値が同一でも異なるobject_idが返却されるオブジェクトの場合、newメソッドで対象のClassからオブジェクトが生成することが可能。
- オブジェクトを1つしか持つことができないメリットとして、メモリ消費を抑えることが挙げられる。文字列またはシンボルどちらでも可能な場合にシンボルが好ましいのはこの理由から。