new
とinitialize
まぎらわしいですし、わかりにくいですよね。
さらに、わかりにくくなるかもしれませんが、実はもう一つ大事なメソッドがあります allocate
です。
例えば Greeting というクラスがあったとします。
通常は Greeting.new
として Greeting のインスタンスを生成します。
ruby
1Greeting.new # => #<Greeting:0x007fc9848da040>
ですね。
実は Greeting のインスタンスを生成するには、もう1つ方法があって、それが先程の allocate
です。
ruby
1Greeting.allocate # => #<Greeting:0x007fc9874adf00>
はい。こちらでも、ちゃんとGreeting のインスタンスが生成されました。
さて、Greetingクラスに morning メソッドを追加しましょう
ruby
1class Greeting
2 def morning
3 puts 'おはよう'
4 end
5end
で、newとallocateを試してみましょう
ruby
1Greeting.new.morning # => おはよう
2Greeting.allocate.morning # => おはよう
同じですね。new
でもallocate
でもGreetingクラスのインスタンスが生成されるのでGreetingクラスの
インスタンスメソッドである #morging
はちゃんと実行できます。
さて、initialize
を使ってみましょう。
例の初期化をするメソッドです。
この場合は挨拶に含める相手の名前を保存する @name というインスタン変数を初期化してみます。
ruby
1class Greeting
2 def initialize(name)
3 @name = name
4 end
5
6 def morning
7 puts "#{@name}さん。おはよう"
8 end
9end
initialize
メソッドを追加しました。
初期化というより初期値の設定といった方がいいかもしれませんね。
そして morning
メソッドも initialize
で初期化した @name を使うように変更しました。
また、newとallocateを試してみましょう
ruby
1Greeting.new.morning # => ArgumentError: wrong number of arguments (given 0, expected 1)
2Greeting.allocate.morning # => さん。おはよう
あれあれ? new
は例外が発生しました。引数の数が1であるべきなのに0だという例外です。
一方 allocate
は例外は発生しませんでしたが @name が表示されていません。
つまり
new
すると、new
の処理過程の中で initialize
が呼ばれているので、引数が必要な initialize
が
呼び出された時点で ArgumentError が発生する
allocate
は initialize
を呼ばないので ArgumentError は発生しないものの @name は空のまま
という事です。
さて、では initialize
に引数を渡すにはどうしたらよいでしょう。
Greeting.allocate
で Greeting インスタンス を生成して、その initialize
メソッドを読んであげればいいのですが
ruby
1Greeting.allocate.initialize('hana-da').morning # => NoMethodError: private method `initialize' called for #<Greeting:0x007fc985972b78>
initialize
は外から呼べないというのはこうこう風になるという事です。
そこで、 new
は allocate
して initialize
するメソッドだった事を思い出しつつ
new
に initialize
に渡したい引数を渡してみます。
ruby
1Greeting.new('hana-da').morning # => hana-daさん。おはよう
やったー!!!!
これで初期化(初期値が設定)されたインスタンスに対しmoringメソッドを呼ぶ事で、ちゃんと挨拶ができるように
なりました。
ruby
1%w(Ringo Dingo Bingo).each do |name|
2 Greeting.new(name).morning
3end
4# Ringoさん。おはよう
5# Dingoさん。おはよう
6# Bingoさん。おはよう
いやー便利です。
さて。ここで initialize
は必須なのか? という話
特に必須ではないです。
initialize を定義せずに、かわりに @name に値を設定する name= メソッドを追加してあげましょう
ruby
1class Greeting
2 def name=(name)
3 @name = name
4 end
5
6 def morning
7 puts "#{@name}さん。おはよう"
8 end
9end
こうすると
ruby
1g = Greeting.new
2g.morning # => さん。おはよう
initialize を定義していないので引数なしでも ArgumentError は発生しませんが、@name もからっぽです。
そこで morning を呼ぶ前に name= で @name に値をセットしてあげると
ruby
1g = Greeting.new # => #<Greeting:0x007fc984929af0>
2g.name = 'hana-da' # => "hana-da"
3g.morning # => hana-daさん。おはよう
名前でました!!!
でもこうやって1つ1つ設定するの面倒ですよね。今回は @name だけですが複雑なクラスになると沢山のインスタンス変数を
使ったりします。
そういう初期化(初期値の設定)を initilize メソッドにまとめておくととっても便利。というお話でした。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。