• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:インスタンスとオブジェクト)

インスタンスとオブジェクトについての違いと理解方法

このQ&Aのポイント
  • ローカル変数はメソッドごとに異なる変数として扱われ、インスタンス変数は同じインスタンス内であればメソッド定義を超えてその値を参照したり、変更したりできます。
  • インスタンス変数は、インスタンスごとに違う値を持ち、インスタンスがある間は値を保持しておいて何度でも利用することができます。
  • 一方、ローカル変数はメソッド呼び出しごとに新しく割り当てられるため、メソッドから抜けると値を忘れてしまいます。

質問者が選んだベストアンサー

  • ベストアンサー
  • siffon9
  • ベストアンサー率64% (136/211)
回答No.2

こんにちは これは実際にクラスを定義して説明しないと分かりにくいのかなと思います。 なので簡単なプログラムを書いてみました。 (段付けに全角のスペースを使用しているので実行させる場合は半角スペースに書き換えが必要です) 後半の# => の右に書いてあるのがプログラムを実行したときに表示される文字です。 ------------------------------- class Person  def set_name(name)   @name = name   puts "Set @name : #{@name}"  end  def print_name   puts "My name is #{@name}"  end  def set_age(age)   var = age   puts "Set age : #{var}"  end  def set_height(height)   var = height   puts "Set height : #{var}"  end end taro = Person.new taro.set_name("Taro") # => Set @name : Taro taro.print_name # => My name is Taro taro.set_age(20) # => Set age : 20 taro.set_height(170) # => Set height : 170 jiro = Person.new jiro.set_name("Jiro") # => Set @name : Jiro jiro.print_name # => My name is Taro ------------------------------- 前半でPersonというクラスを定義しています。このクラスでは4個のメソッドと、@nameというインスタンス変数、下の二つのメソッドではvarというローカル変数を使用しています。 このクラスの定義が、言い換えれば設計図になります。 例えば一つの自動車の設計図から実体としての自動車がいくつも製造できるように、クラスの定義からも実体をいくつも作ることができて、この実体をインスタンスと言います。では、実体としてのインスタンスが何処にできるかというとコンピュータのメモリ空間の中に作られるのですね。具体的にどうなっているかは、今のところはあまり気にする必要はありません。 ではクラスの定義(設計図)からどうやってインスタンス(実体)を作るのかというと、それが次のプログラム行になります。 taro = Person.new jiro = Person.new ここではtaroとjiroという二つのインスタンス(実体)を作っています。インスタンスの中にはクラスの定義のとおりに@nameというインスタンス変数が存在して、4個のメソッドが使用可能になります。また、taroとjiroはそれぞれ個別の実体になります。ですからそれぞれの中に存在するインスタンス変数@nameもそれぞれ別のものとなります。 ここで、taroというインスタンスをみましょう。 taro.set_name("Taro") # => Set @name : Taro taro.print_name # => My name is Taro taroインスタンスのset_nameメソッドを利用して、インスタンス変数@nameに"Taro"という値をセットしていますね。次にtaroインスタンスのprint_nameというメソッドを利用して@nameの値を読み出して表示しています。同じインスタンス内のあるメソッドで設定したインスタンス変数の値が、同じインスタンス内の別のメソッドで読むことができるということですよね。つまりインスタンス変数はインスタンスの中にメソッドとは関係なく存在して値が保持されるということです。これが「同じインスタンス内であればメソッド定義を越えてその値を保持したままでいられる」という意味です。 つぎにローカル変数についてですが、 ローカル変数というのはメソッドの実行開始時に、コンピュータのメモリ空間のどこかに生成されてメソッドに実行が終わると破棄されて存在しなくなってしまいます。 taro.set_age(20) # => Set age : 20 taro.set_height(170) # => Set height : 170 このプログラム行では各の行で、taroインスタンスのset_ageメソッドとset_heghtメソッドが実行して、それぞれのメソッドでvarというローカル変数が使用されています。 set_ageメソッド開始時に作られたvarというローカル変数はset_ageメソッド終了時に破棄されます。そしてset_heghtメソッド実行時にまた別に作られます。つまりset_ageメソッドで使用したローカル変数varとset_hetghtメソッドで使用されたローカル変数は同じ名前ですが、まったくの別物ということですね。 ですからインスタンス変数の様に、あるメソッドでセットした値を別のメソッドで読み取るということは当然できません。これが「ローカル変数がメソッドごとに異なる」の意味です。 > hello = "Hello, Ruby." > p hello > puts hello > print hello > > どのメソッドでもローカル変数が持つ値は > 変わらないと思っていたのですが。 この4行のhelloというローカル変数が、ひとまとめで見えない一つのメソッドの中に書かれていると考えてみて下さい。 def 見えないメソッド  hello = "Hello, Ruby."  p hello  puts hello  print hello end 見えないメソッド開始時にhelloというローカル変数が作られて、見えないメソッド終了時にhelloというローカル変数は破棄されます。その間ではhelloは一つの変数として値を保持したまま存在します。 私も詳しく理解しているわけではありませんので、アバウトな説明になってしまいましたが、ご理解の一助にしていただければ幸いです。

noname#197548
質問者

お礼

回答ありがとうございます! 例え話はとても分かりやすいですね。 イメージではそれほど難しくなかったので、 言葉に表すととても長くなってしまい、 大変な思いをさせました。 本では、インスタンス変数を使うには 初期化しないと nil が返されると書かれています。 initialize メソッドで初期化するために あなたが書いてくれたコードを 少し書き換えて実行してみたのですが、 ArgumentError となってしまいます。 また少し調べてみます。 ありがとうございました。

その他の回答 (4)

  • siffon9
  • ベストアンサー率64% (136/211)
回答No.5

こんにちは、No.2です。 > 本では、インスタンス変数を使うには > 初期化しないと nil が返されると書かれています。 そうですね、@nameに値をセットしない(初期化しない)ままprint_nameメソッドを使用するとおかしなことになってしまいますね、失礼いたしました。 仰るとおり初期化をinitializeメソッドで行います。 (例によって段付けの為に全角スペースを使用しています) class Person  def initialize   @name = "no name"  end  以下略 end taro = Person.new taro.print_name # => My name is no name あるいはset_nameメソッドを使用しないでインスタンスを作るときに@nameを設定してしまう場合は以下のようになります。 class Person  def initialize(name)   @name = name  end  以下略 end taro = Person.new("Taro") taro.print_name # => My name is Taro > ArgumentError となってしまいます。 下のinitializeメソッドの例やset_nameメソッドの様に丸括弧をつけてメソッドに与えるデータ(パラメータ)を引数(Argument)といいます。 taro = Person.new("Taro")  の"Taro"の部分ですね。 ArgumentErrorとは引数が必要無いのにメソッドを実行するときに引数をつけた、引数が必要なのに引数をつけなかった、つけた引数の数が必要な数と一致しなかった場合などに発生します。 以上、本題とは外れてしまいましたが補足をさせていただきました。 最後にNo.2のプログラムの最終行は jiro.print_name # => My name is Jiro の誤りでした(表示する内容の誤り)、失礼致しました。

noname#197548
質問者

お礼

ArgumentError は、 インスタンスを作らずに いきなりメソッドへ引数を渡してしまった 僕の間違いでした。 ありがとうございます。

  • notnot
  • ベストアンサー率47% (4900/10358)
回答No.4

インスタンスとオブジェクトは同じ物です。微妙なニュアンスは違いますが、プログラミング上は同じ物と思って大丈夫です。 >・ローカル変数が "メソッドごと" に異なる変数として扱われる 同じ変数名が異なるメソッドで使われていても、それは同じ物で無く、異なる変数であると言うことです。 同じ「太郎」でも、「鈴木家の太郎」と「田中家の太郎」は別人ということ。 >・インスタンス変数は同じ "インスタンス内" であれば、メソッド定義を超えてその値を参照したり、変更したりできます もう少しわかりやすく書き直すと、 「同じオブジェクトのインスタンス変数は、そのオブジェクトに固有の物で、どのメソッドからも同じ物として参照・代入できます。もちろん、異なるオブジェクトの同名のインスタンス変数は別物です」 わかりやすくなってなかったらごめん。 インスタンス変数はオブジェクトの属性のようなものです。よく「自動車クラスの、個々の車がオブジェクト」とかいう例えがされますが、「ある車の色は、誰から見ても同じ色。違う車の色は、また違う(かもしれない)」ということです。 (こういう比喩は厳密には正しくないのであまり囚われないでください)

noname#197548
質問者

お礼

オブジェクトとインスタンスは意味は同じで 使い方が違うだけなのですね。 ローカル変数とインスタンス変数についても 他の方の回答があって やっと理解できました。 ありがとうございます。

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

言語によっては使いわけるものもあるかもしれませんが Rubyではオブジェクトとインスタンスは同義です。 > 分かる人からすると、 > 言っている意味が分からない > なんてことになるんでしょうね。 そういうことでは無いと思います。 どこまで理解できていて、どこが理解できていないのか、を明確にするのは、答える側にも、そしてなにより聞く側にも重要なことです。 ローカル変数/グローバル変数があることを理解していて、その上でインスタンス変数がわからないのか ローカル変数/グローバル変数がそもそも理解できていないのか で、答え方がぜんぜんちがいますから。

noname#197548
質問者

補足

なるほど。 ローカル変数とグローバル変数は分かります。 ローカル変数はアルファベット小文字およびアンダースコアで始まり、 数字を最初に置いてはいけない、と。 グローバル変数は$で始まり、 require メソッドで読み込むと参照・変更ができますね。 インスタンス変数は@で始まり、 class ~ end の中で使う という事しか分かっていませんでした。 あとひとつ、 クラス変数は分かりません。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

どう「わからない」んでしょうか?

noname#197548
質問者

補足

すみません。 分かる人からすると、 言っている意味が分からない なんてことになるんでしょうね。 まずインスタンスが何なのかさえ分かりません。 インスタンスはオブジェクトと 同じ意味ではありませんね? @で始まるものを インスタンス変数と呼ぶのは分かりますが、 インスタンスという言葉がついてる以上、 インスタンスに関わる性質を持っていると思います。 →でも「インスタンス」が分からない。 インスタンス変数が 同じインスタンス内であれば メソッド定義を越えて その値を保持したままでいられるとは、 何のことでしょうか。 →「インスタンス内」とは何かのブロック? ローカル変数がメソッドごとに異なるとは、 どういう意味で何が異なるんでしょうか。 hello = "Hello, Ruby." p hello puts hello print hello どのメソッドでもローカル変数が持つ値は 変わらないと思っていたのですが。

関連するQ&A