LoginSignup
6
8

More than 5 years have passed since last update.

Rubyのattr_accessorとインスタンス変数

Last updated at Posted at 2017-10-09

Rubyのattr_accessor@インスタンス変数について調べたのでまとめました。

外部からのインスタンス変数へのアクセス

class Foo
  attr_accessor :bar
end

foo = Foo.new
foo.bar = 'instance!!!'
foo.bar # => "instance!!!"

foo.bar = 'instance!!!' は一見、変数へ代入しているように見えますが、実態はattr_accessor が作成した以下のようなFoo#bar= メソッドを呼び出しています。

def bar=(val)
  @bar = val
end

従ってfoo.bar = 'instance!!!' の右辺はメソッドの引数です。また、Rubyにはsyntax sugarが用意されており、foo.bar= と書かなくてもfoo.bar = のように代入しているみたいに書けるのです。

参照についても同じくfoo.barは、@bar を返すbar という以下のようなメソッドを呼び出しています。

def bar
  @bar
end

インスタンスメソッドからのアクセス

class Foo
  attr_accessor :bar

  def method_baz
    p "#{@bar} from method_baz"
  end 

  # attr_accessor :bar が定義されていなければ、barメソッドを呼び出せすNameErrorとなる
  def method_qux
    p "#{bar} from method_qux"
  end
end

foo = Foo.new
foo.bar = 'instance!!!'
foo.method_baz # => "instance!!! from method_baz"
foo.method_qux # => "instance!!! from method_qux"

method_qux では@ を付けなくてもインスタンス変数を参照しています。
これも上記と同じくattr_accessor が作成した@bar を返すbar というメソッドを呼び出しているからです。
従ってアクセサが定義されていなければ、method_qux はエラーになります。

インスタンスメソッドからのアクセス 2

class Foo
  attr_accessor :bar

  def method_quux
    p bar
    bar = 'blue!!!'
    p bar
    p @bar
    p bar()
  end 
end

foo = Foo.new
foo.bar = 'red!!!'
foo.method_quux # => "red!!!"
                # => "blue!!!"
                # => "red!!!"
                # => "red!!!"

method_quux では1回目のp bar と2回目のp bar で出力される値が異なります。
これは1回目のp bar ではattr_accessor が作成している@bar を返すbar というメソッドを呼び出しているのに対して、2回目のp bar では直前に定義された同名のローカル変数を参照しているためです。
この場合、インスタンス変数を参照したい時は素直に@bar とするかbar()と括弧を付けて明示的にメソッド呼び出しにする必要があります。

参考

以下の記事が参考になりました。
http://qiita.com/mogulla3/items/cd4d6e188c34c6819709

6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8