29
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Ruby】attr_accessor、attr_reader、attr_writerの違いを例から理解する

Last updated at Posted at 2019-10-27

目的

Rubyのattr_accessor、attr_reader、attr_writerについて、色々調べたり、手を動かしたりして、理解できたことをまとめておきます。

attr_accessor、attr_reader、attr_writer の定義

まずは、Rubyリファレンスで定義を見てみましょう。

attr_readerメソッドは、クラスやモジュールにインスタンス変数を読み出すためのアクセサメソッドを定義します。引数には、インスタンス変数名をシンボルか文字列で指定します(複数指定できます)。戻り値はnilです。

attr_writerメソッドは、クラスやモジュールにインスタンス変数を書き込むためのアクセサメソッドを定義します。引数には、インスタンス変数名をシンボルか文字列で指定します(複数指定できます)。戻り値はnilです。

attr_accessorメソッドは、クラスやモジュールにインスタンス変数を読み書きするためのアクセサメソッドを定義します。引数には、インスタンス変数名をシンボルか文字列で指定します(複数指定できます)。戻り値はnilです。

定義からは少し分かりづらいかもしれませんが、コードから理解してみましょう。

最初からまとめ

簡潔に言うと、

  • attr_readerメソッドは、インスタンス変数を呼び出すメソッドを定義する。
  • attr_writerメソッドは、インスタンス変数を書き込みメソッドを定義する。
  • attr_accessorメソッドは、インスタンス変数を読み書きメソッドを定義する。

これを心に留めておいて、例を見てみましょう。

それぞれの意味

attr_readerメソッド

実は、attr_readerメソッドは以下のインスタンスメソッドと同じ意味です。

  def name
    @name
  end

例:

class Member
  def name
    @name
  end
end
member = Member.new
member.name = "Chimei" # => NoMethodError (undefined method 'name=')
member.name # => nil

attr_readerメソッドはクラスからインスタンス変数を読み出すしかできないので、
ここでmember.name = "Chimei"、値を書き込みしようとするとNoMethodError (undefined method 'name=')エラーが出てきます。
値が入ってないから、もちろんmember.nameはnilとなっています。

attr_writerメソッド

attr_writerメソッドは以下のインスタンスメソッドと同じ意味です。

  def name=(name)
    @name = name
  end

例:

class Member
  def name
    @name
  end
  def name=(name)
    @name = name
  end
end
member = Member.new
member.name # => nil
member.name = "Chimei" # => "Chimei"
member.name # =>  "Chimei"

最初はmember.nameはnilですが、attr_readerメソッドはクラスにインスタンス変数を書き込みできるので、member.name = "Chimei"で値を書き込んで、そしてmember.nameで値を確認してみると、確かに値が入っていましたね。

attr_accessorメソッド

attr_readerメソッドとattr_writerメソッドのフュージョン:point_right::point_left:です。
つまり、クラスにインスタンス変数を読み出しだけではなく、書き込みもできる。
以下の二つ例が同じ意味です。

class Member
  attr_reader :name
  attr_writer :name
end

member = Member.new
member.name = "Chimei" # => "Chimei"
member.name # => "Chimei"
class Member
  attr_accessor :name
end
member = Member.new
member.name = "Chimei"
member.name # => "Chimei"

三つ一緒に使ってみる

例1:

class Profile
  attr_reader :name
  attr_writer :job
  attr_accessor :experience
end

profile = Profile.new

# 現在、値が何も入ってないから、値を書き込んでみよう
profile.name = "Shane" # => NoMethodError (undefined method `name=') 【書き込みできない】
profile.job = "teacher" # => "teacher"
profile.experience = 8 # => 8

# 値を確認
profile.name # => nil【書き込みできないから、値がnil】
profile.job # => NoMethodError (undefined method `job') 【読み出しできない】
profile.experience # => 8

例2:

class Profile
  attr_reader :name
  attr_writer :job
  attr_accessor :experience

  def initialize(name, job, experience)
    @name = name
    @job = job
    @experience = experience
  end

  def intro
    "Hi, I am #{@name}. I work as a #{@job} for #{@experience} years."
  end
end

profile = Profile.new("Shane", "teacher", 8)
profile.intro # => "Hi, I am Shane. I work as a teacher for 8 years."

# 読み出す場合
profile.name # => "Shane"
profile.job # => NoMethodError (undefined method `age') 【読み出しできない(書き込むだけOK)】
profile.experience # => 8

# 値を変更しようとすると
profile.name = "Sid" # => NoMethodError (undefined method `name=') 【書き込みできない(読み出すだけOK)】
profile.job = "headhunter" # => "headhunter"
profile.experience = 3 # => 3

# 結果を確認
profile.intro # => "Hi, I am Shane. I work as a headhunter for 3 years."

initializeメソッドはインスタンスを初期化(ここでProfile.new)時、自動で実行します。
そこで、三つの引数を値が入りました。 なので、1番目のprofile.introが特に問題ないです。

ですが、profile.name = "Sid"で値を変更できないので、
2番目のprofile.introは nameの値は元々のShaneで出力してしまいました。

もう一度まとめ

attr_reader:インスタンス変数を呼び出すメソッドだけを定義したので、書き込みできない。
attr_writer:インスタンス変数を書き込みメソッドだけを定義したので、呼び出しできない。
attr_accessor:インスタンス変数を呼び出すと書き込むメソッドを定義しましたので、どちらでもできる。

######ここまでお読みいただきありがとうございました。多分文法上おかしいと思いますが、来日して2年目ですので日本語まだ勉強中です。文法ミスや誤字がありましたらあらかじめご了承ください。:pray_tone1:もちろん編集リクエストでご意見いただければと思います。

参考文献

https://www.rubyguides.com/2018/11/attr_accessor/
https://ref.xaio.jp/ruby/classes/module/attr_accessor
https://ref.xaio.jp/ruby/classes/module/attr_reader
https://ref.xaio.jp/ruby/classes/module/attr_writer

29
20
2

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
29
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?