Help us understand the problem. What is going on with this article?

attr_accessor とは "クラス外からインスタンス変数の読み書きができるもの。"

More than 1 year has passed since last update.

attr_accessor について。
よくattr_accessor は 「ゲッターとセッターを自動的に定義してくれるもの。」というのは見かけていたのですが、で?何それって感じでした。

これをruby初心者に説明するにはインスタンス変数についてから説明しないとスッとは入ってこないと僕は思いますのでそこから説明します。

インスタンス変数

# @から始まるクラス内の変数
# ↓こういうの
@name   

これはClass内の、さらにどのメソッドでも使用することができますが、クラス外では通常使用することができません。クラス外から呼び出すには、下記のようにメソッドを用意し、そこからインスタンス変数を呼び出します。

class User
 def initialize(name)
    @name = name
  end

 def get_name #通常rubyではこのようなメソッド名はつけず、"def name"にするのが一般的です。今回はインスタンス変数名と被らないようにこのようにしています。
   @name
 end
end
irb(main):012:0> u = User.new("tes-taro")
=> #<User:0x00007f832bdcc048 @name="tes-taro">
irb(main):013:0> u.name                             #---1
Traceback (most recent call last):
        1: from (irb):13
NoMethodError (undefined method `name' for #<User:0x00007f832bdcc048 @name="tes-taro">)
irb(main):014:0> u.get_name                         #---2
=> "tes-taro"
irb(main):015:0>

上記は定義したUser クラスからインスタンスUを作り、"u.name"(#---1)でインスタンス変数@nameにアクセスしようとしましたが、そんなメソッドはないとエラーで怒られています。
次に "u.get_name"(#---2)からクラス内で定義したget_nameメソッドを呼び出すことで、メソッドを通じて@nameインスタンスにアクセスすることができました。これがいわゆるゲッターメソッドということになります。

attr_readerメソッド(アクセスメソッド)

ただ、クラスに呼び出す予定の変数がたくさんあった場合、このゲッターメソッドをたくさん書かないと行けなくなります。それはめんどくさいですし、コードが無駄に長くなってしまいますので、それを解決するためのものがattr_readerなるメソッドです。

class User
 attr_reader :name

 def initialize(name)
   @name = name
 end

 # def get_name
 #   @name
 # end
end
irb(main):002:0> u = User.new("test-taro")
=> #<User:0x00007f832bb94938 @name="test-taro">
irb(main):003:0> u.name                 #---3
=> "test-taro"

"attr_reader :name"をコードに加えることで、先ほどはエラーを出されていた "u.name"(#---3)から直接インスタンス変数 @name を呼び出すことに成功しています。

セッターとattr_writter

ゲッターとattr_readerについてわかるとセッターとそれを簡単に構築するコードの存在についてはピンと来る方も多いと思います。

  • セッターは外部からインスタンス変数を書き込みことができるようにするメソッド
  • attr_writterはそれ(セッター)を簡単・短縮して実装するもの

です。

実際にコードを見ていきましょう。
まず、現状のコードでは

irb(main):003:0> u.name
=> "test-taro"
irb(main):004:0> u.name = "test-hanako"         #---4
Traceback (most recent call last):       
        1: from (irb):4
NoMethodError (undefined method `name=' for #<User:0x00007f832bb94938 @name="test-taro">)
Did you mean?  name

このように(#---4以下)、インスタンスメソッドを呼び出すことはできても書き換えることはできません。これを書き換えることができるようにコードを変えます。

class User

 attr_reader :name

 def initialize(name)
    @name = name
  end

 # セッターメソッド
 def set_name(new_name)   #作法的には"def name=(new_name)"と書くのが正しい。今回はわかりやすさ(個人的に)を重視してこちらで書きます。
    @name = new_name
 end
end

上記のセッターメソッドを追記することで、このメソッドを通じてインスタンス変数を書き換えることができます。下記のコンソールから確認しましょう。

irb(main):002:0> u = User.new("test-taro")
=> #<User:0x00007f832b1abb60 @name="test-taro">
irb(main):003:0> u.name
=> "test-taro"
irb(main):004:0> u.set_name("test-hanako")  #---5
=> "test-hanako"
irb(main):005:0> u.name
=> "test-hanako"                            

"u.set_name("test-hanako")" (#---5部分)にからインスタンス変数@nameを書き換えることができたのがわかります。
ゲッターメソッド同様なんども外部からインスタンス変数を変更するためのメソッドを書く
手間を省くためにセッター用のアクセスメソッドを書き加えます。

class User

 attr_reader :name
 attr_writer :name 


 def initialize(name)
    @name = name
  end

  #セッター
  # def set_name(new_name)
  #   @name = new_name
  # end
end

"attr_writer :name"を追加しまし、先ほど使用していたセッターメソッドをコメントアウトしました。
"attr_writer :name"により、外部から直接インスタンス変数を書き換えることができるようになります。

irb(main):002:0> u = User.new("test-taro")
=> #<User:0x00007f832bde62e0 @name="test-taro">
irb(main):003:0> u.name = "test-hanako"          #---6
=> "test-hanako"
irb(main):004:0> u.name
=> "test-hanako"

"u.name = "test-hanako"" (#---6部分)でわかるように直接インスタンス変数@nameを書き換えています。

attr_accessor

やっと attr_accessor がの説明になります。
"attr_accessor" とはここまで見てきたゲッター・セッターのアクセスメソッドをまとめて記述するものになります。

class User
 # 外部からの@nameの呼び出し・変更が可能
 attr_accessor :name

 # attr_reader :name
 # attr_writer :name

 def initialize(name)
    @name = name
 end
end
irb(main):002:0> u = User.new("test-taro")
=> #<User:0x00007f832ab68b40 @name="test-taro">
irb(main):003:0> u.name
=> "test-taro"
irb(main):004:0> u.name = "test-hanako"
=> "test-hanako"
irb(main):005:0> u.name
=> "test-hanako"

"attr_accessor :name" ひとつでインスタンス変数へのアクセスが可能となったのがわかります。
これでattr_accessorの使い方がわかったのではないでしょうか。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away