インスタンス変数とメソッドの住んでいる場所 | Dev Driven 開発・デザインチーム インスタンス変数とメソッドの住んでいる場所 | 働くひとと組織の健康を創る iCARE

BLOG

インスタンス変数とメソッドの住んでいる場所

2021/10/26

こんにちは、サーバーサイドエンジニアの寺井(@krpk1900_dev)です。

iCAREでは毎週たくさんの勉強会が開催されており、最近では@willnetさんが開催してくださったメタプログラミングRubyの読書会が始まりました。
今回はメタプログラミングRuby第2章「オブジェクトモデル」の中で印象的だった 「インスタンス変数とメソッドの住んでいる場所は異なる」 というテーマについて書いていきたいと思います。

1.メタプロの世界から見たインスタンス変数とメソッドの住んでいる場所

以下はメタプログラミングRubyの内容を参考にしています。
下のサンプルコードを見てみてください。
オブジェクトはインスタンス変数とメソッドを持っています。

class MyClass
    def my_method
        @v = 1
    end
end
obj = MyClass.new
obj.class

オブジェクトにインスタンス変数が含まれていることはobj.instance_variablesを呼び出すことで確認できます。

obj.my_method
obj.instance_variables # => [:@v]

メソッドについては、obj.methodsを呼び出せばメソッドの一覧を取得できます。

obj.methods.grep(/my/) # => [:my_method]

しかしこの書籍では、

「オブジェクトにはメソッドはない」

という文章が出てきます。

それではメソッドはどこにあるのでしょうか?

実際にはオブジェクトが持っているものはメソッドではなく、インスタンス変数とクラスへの参照です。
インスタンス変数は同じクラスのオブジェクトであっても数が異なることがあったり、値が共有されません。インスタンス変数は個々のオブジェクトに住んでいるからです。
一方メソッドについては、共通のクラスを持つオブジェクトであればメソッドも共通しています。
つまりメソッドはオブジェクトではなくクラスに住んでいることになります。

2.メモリの世界から見たインスタンス変数とメソッドの住んでいる場所

ここまでのことを読んで私はメモリのことを思い出しました。
最近プライベートで「オブジェクト指向でなぜ作るか」という書籍を読んでいて、第5章でメソッドとインスタンス変数は異なるメモリ領域に保存されるということが書かれていました。
以下は「オブジェクト指向でなぜ作るか」の内容を参考にしています。

プログラムのメモリ領域は基本的には、静的領域、ヒープ領域、スタック領域の3つに別れています。

  • 静的領域はプログラムの開始時に確保され、静的な変数、すなわちグローバル変数やプログラムの命令を実行可能な形式に変換したコード情報が格納されます。
  • ヒープ領域はプログラムの実行時に動的に確保するためのメモリ領域で、heap(たくさん、山ほど)が意味する通りプログラム開始時にたくさんのメモリ領域があらかじめ確保されます。ガベッジコレクションの対象になる領域はこのヒープ領域に当たります。
  • スタック領域はスレッド制御のために使われるメモリ領域で、メソッドの引数やローカル変数、返り値などが格納される領域です。

オブジェクト指向プログラミングでは、インスタンスを作る前に対応するクラスの情報、すなわちメソッドに書かれたコード情報などがメモリにロードされます。
同じクラスから作られたインスタンスであっても、インスタンス変数の値はそれぞれのインスタンスによって変わりますが、メソッドに書かれたコード情報は変わらないため、ロードされる領域は静的領域になります。
 
 
 
それでは、インスタンスについてはどのようになっているのでしょうか?
newメソッドのようなインスタンスを作るような命令が実行されると、そのクラスのインスタンス変数を格納するために必要な大きさのメモリがヒープ領域に割り当てられます。
そしてこのとき、インスタンスを指定してメソッドを呼び出す仕組みを実現するために、インスタンスから静的領域にあるクラス情報への対応づけが行われます。

この状態を示した図は下のような図になります。

(オブジェクト指向でなぜ作るか 図5.8を参考に作成)

この図はまさに、メタプログラミングRubyで出てきた

「実際にはオブジェクトが持っているものはメソッドではなく、インスタンス変数とクラスへの参照です。」

という解説と完全に一致しています。

3.感想

メタプロの世界から見た「インスタンス変数とメソッドの住んでいる場所は異なる」と、メモリの世界から見た「インスタンス変数とメソッドの住んでいる場所は異なる」が繋がり、とても印象に残りました。

iCAREでの学びとプライベートでの学びの相乗効果を感じられるようなとても有意義な勉強会を開催してくださった@willnetさん、いつもありがとうございます!