質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

2回答

18182閲覧

Rubyの学習でinitializeメソッドとnewメソッドがわかりません。

techtottori

総合スコア26

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

3グッド

12クリップ

投稿2016/10/17 01:54

#前提
作りながら学ぶRuby第二版を進めていて、本文は一部抜粋させていただいております。
質問回数が少ないため、引用方法など間違えているかもしれませんが、その際はご指摘ください。

属性に最初に持たせる値を決めるために、初期化する方法も必要ですね。Rubyでは、あるクラスのインスタンスを作成するときにはnewメソッドを呼び出すことはすでに説明しました。そのクラスに操作「initialize」メソッドが用意されている時は、newメソッドはinitializeメソッドを呼び出して初期化の処理に利用します。例えば、Studentクラスが名前を格納するインスタンス変数「@name」と、年齢を格納するインスタンス変数「@age」を持っているとして、初期化のためにinitializeメソッドを用意するには、メソッドを定義するときに使う予約語「def」を使って次のように書きます。なお、このinitializeメソッドは、newメソッドの処理の内部でインスタンスの初期化のために使うメソッドなので、インスタンスの外部からは呼び出すことができません。

#質問事項
0. なぜ初期化するのか
0. initializeメソッドとnewメソッドは何を行っているのか?
0. newメソッドの処理の内部でインスタンスの初期化のために使うメソッドなので、インスタンスの外部からは呼び出すことができませんとはどういう意味なのか?

beginer190105, hana-da, banjo👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

newinitializeまぎらわしいですし、わかりにくいですよね。
さらに、わかりにくくなるかもしれませんが、実はもう一つ大事なメソッドがあります allocate です。

例えば Greeting というクラスがあったとします。

class Greeting end

通常は 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

で、newallocateを試してみましょう

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 を使うように変更しました。

また、newallocateを試してみましょう

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 が発生する

  • allocateinitialize を呼ばないので ArgumentError は発生しないものの @name は空のまま

という事です。

さて、では initialize に引数を渡すにはどうしたらよいでしょう。

Greeting.allocate で Greeting インスタンス を生成して、その initialize メソッドを読んであげればいいのですが

ruby

1Greeting.allocate.initialize('hana-da').morning # => NoMethodError: private method `initialize' called for #<Greeting:0x007fc985972b78>

initializeは外から呼べないというのはこうこう風になるという事です。

そこで、 newallocate して initialize するメソッドだった事を思い出しつつ
newinitialize に渡したい引数を渡してみます。

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 メソッドにまとめておくととっても便利。というお話でした。

投稿2016/10/18 00:53

hana-da

総合スコア1728

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

質問1「なぜ初期化するのか」

端的に言えば、「必要だから」です。多くの場合、オブジェクトが正しく動作するためには、内部が一定の状態を持っている必要があります。それを整えるために使うメカニズムがinitializeです。逆を返せば、「親クラスにあるものそのままでいい」というような状況なら、initialize自体を書かなくて構いません。

質問2「initializeメソッドとnewメソッド何を行っているのか」

newが行う作業は、大きく2つにわけられます。

  1. 新しいインスタンスが使うメモリを確保する
  2. initializeを呼び出して、内部状態を整える(newへの引数がinitializeに渡されます)

質問3「外部から呼べない、とは?」

Rubyの場合、initializeという名前のメソッドは自動的にprivateとなり、オブジェクト.initializeの形の呼び出しができなくなります。同じクラスの中からinitializeだけで呼ぶ、あるいは__send__で無理やり呼ぶことは可能です。

投稿2016/10/17 02:18

maisumakun

総合スコア145941

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問