なぜコンストラクタは多段ロケットみたいなの?
Rubyではオブジェクトをインスタンス化するのにnewメソッドを使う。でも実際にはinitializeというメソッドが呼ばれる。なんでこの2つが一致していないのか、どうも分からない。str=String.intialize("hello")とかでいいんじゃないの?
The Ruby Wayにはちょっと凝ったコンストラクタの例が出ている。無駄に長いので短いのを作ると、こんな感じ。
class Rectangle def initialize(s1,s2) @s1, @s2 = s1, s2 end def Rectangle.square(s) new(s,s) end def inspect "#@s1 #@s2" end end a = Rectangle.new(3,5) # 3 5 b = Rectangle.square(5) # 5 5
うーん、newはクラスメソッド(実際にはClassオブジェクトの特異メソッド)だから実行できるけど、ただ単に「def initialize」で定義したインスタンスメソッドは、インスタンスを生成する前には呼びようがない。そうか、だからnewというクラスメソッドを用意してるのか。newメソッドとコンストラクタに相当するメソッドを分離することで、ユーザーがクラスメソッドを理解しなくても、ひとまず普通のインスタンスメソッドを使ってコンストラクタが書ける。記法として一貫性がある。もしこれが、
class Rectangle def Rectangle.new(s1,s2) @s1, @s2 = s1, s2 end end
と書かないといけないとすると、ちょっとヘンなことになる。実装としては何も不思議なところはないけど(いやあるんだけど……。つまりclassの宣言に見えてるものって実際にはClassオブジェクトを作ってるってこと? そんな気がする)、クラスを定義しているように見える構文の中で、いきなりクラスメソッドを呼んでいるように見えるのでは意味が分からないし。
しかsも、newとinitializeを別々にしてクラスメソッドを経由してコンストラクタを呼ぶことで上記のように応用が効く。
そうか、「Rectangle.new」というのはClassオブジェクトとしてインスタンス化したRectangleって奴の特異メソッドで、なんというか記法としても自然だし「オブジェクトーメッセージ」という枠組みの一貫性も保たれてていいってことか。ということを考えると、ほかの言語が断然気になる。今度調べてみよう。
しかし、それにしてもinitializeはinitという名前でも良かったのじゃないかとタイプするたびに思うのはぼくだけか。