インスタンス変数についてまとめました。
インスタンス変数
@
で始まる変数はインスタンス変数であり、カレントオブジェクトself
に属しています。初期化されていないインスタンス変数を参照した時の値はnil
であり、存在も確認できません。普通のローカル変数の場合、初期化されてない変数を参照しようとすると NameError が発生するところが違います。
class MyClass def name=(value) @name = value end def name @name end end obj = MyClass.new obj.instance_variables #=> [] obj.name #=> nil obj.name = "hoge" # @name が初期化された obj.instance_variables #=> [:@name] obj.name #=> "hoge"
クラスインスタンス変数
インスタンス変数はカレントオブジェクトself
に属しているため、Class クラスのオブジェクトに属しているインスタンス変数のことをクラスインスタンス変数といいます。
クラスオブジェクトのインスタンス変数とクラスがインスタンス化されたオブジェクトのインスタンス変数は別物です。
class MyClass @name = "hoge" # MyClassがselfになる def self.class_attribute @name end def name=(value) @name = value end def name @name end end MyClass.instance_variables #=> [:@name] MyClass.instance_variable_get(:@name) #=> "hoge" MyClass.class_attribute #=> "hoge" obj = MyClass.new obj.name = "fuga" obj.name #=> "fuga" MyClass.class_attribute #=> "hoge" obj.instance_variable_get(:@name) #=> "fuga" MyClass.instance_variable_get(:@name) #=> "hoge"
attr_accessor / attr_reader / attr_writer
いわゆる getter や setter とよばれるインスタンス変数へのアクセサを定義するメソッド (クラスマクロ) がModule#attr_*
で定義されています。
メソッド | 機能 |
---|---|
Module#attr_accessor | インスタンス変数に対する読み取りと書き込みメソッドを定義する。 |
Module#attr_reader | インスタンス変数の読み取りメソッドを定義する。 |
Module#attr_writer | インスタンス変数への書き込みメソッドを定義する。 |
メソッドを使用するとアクセサのメソッドが定義されます。
class AccesorClass attr_accessor :name, :age end AccesorClass.public_instance_methods(false) #=> [:name, :name=, :age, :age=] class ReaderClass attr_reader :gender end ReaderClass.public_instance_methods(false) #=> [:gender] class WriterClass attr_writer :memo end WriterClass.public_instance_methods(false) #=> [:memo=]
Module#attr_*
で実際に定義されるのは以下のようなメソッドです。
def my_attribute=(value) @my_attribute = value end def my_attribute @my_attribute end
初めは間違えやすいですが、例えば以下のようなインスタンスメソッドがあったとして、name
は変数を直接参照している訳ではなく、実はメソッドだということがわかります。
attr_accessor :name def hello_method puts "hello #{name}!!" end
クラスインスタンス変数を定義したい場合
クラスインスタンス変数へのアクセサを定義したい場合は特異クラスに記述します。
class MyClass class << self attr_accessor :name end end MyClass.name = "Bob" MyClass.name #=> "Bob"
インスタンス変数関連のメソッド
インスタンス変数を操作するためのメソッドには以下のようなものが存在します。
メソッド | 機能 |
---|---|
Object#instance_variables | オブジェクトのインスタンス変数名を返す |
Object#instance_variable_get | オブジェクトの指定したインスタンス変数の値を取得して返す |
Object#instance_variable_set | オブジェクトの指定したインスタンス変数に値を設定する |
Object#remove_instance_variable | オブジェクトから指定したインスタンス変数を取り除き値を返す |
Object#instance_variable_defined? | 指定したインスタンス変数が定義されていたら真を返す |
class Foo def intialize @name = 'taro' end end obj = Foo.new obj.instance_variables #=> [:@name] obj.instance_variable_get(:@name) #=> "bar" obj.instance_variable_set(:@age, 30) #=> 30 obj.instance_variables #=> [:@name, :@age] obj.remove_instance_variable(:@name) #=> "bar" obj.instance_variable_defined?(:@name) #=> false obj.instance_variable_defined?(:@age) #=> true