0
0

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 3 years have passed since last update.

attr_accessorがあれば、attr_reader、attr_writerはいらない?

Posted at

はじめに

インスタンス変数へのアクセサメソッド(読み書きのためのメソッド)について、学んだことをまとめます。 「attr_accessor?とりあえず、最初に書いとくお決まりの言葉でしょ。」という方は、ぜひご覧ください。

アクセサメソッド

3つのアクセサメソッドの特徴は以下のとおりです。

attr_reader

インスタンス変数への読み込みを行うためのメソッドを定義します。

attr_writer

インスタンス変数への書き込みを行うためのメソッドを定義します。

attr_accessor

インスタンス変数への書き込み、読み込みを行うためのメソッドを定義します。

アクセサメソッドを使わない場合

attr.rb
class User
  def name=(name) #nameへの書き込みメソッド(セッター)を定義
    @name = name
  end

  def name #nameへの読み込みメソッド(ゲッター)を定義
    @name
  end

  def age=(age) #ageへの書き込みメソッド(セッター)を定義
    @age = age
  end

  def age #ageへの読み込みメソッド(ゲッター)を定義
    @age
  end

end

  user = User.new #Userクラスのインスタンスを作成

  user.name = "ruby太郎" #userにnameを書き込み
  user.age = 20 #userにageを書き込み

  puts "名前:#{user.name}" #userのnameを読み込んで出力
  puts "年齢:#{user.age}歳" #userのageを読み込んで出力

=> "名前:ruby太郎"
   "年齢:20歳"
```
<h3>attr_readerを使う場合</h3>
上記コードから読み込みメソッドの定義を削除し、以下のコードを追加します。

```
attr_reader :name, :age
```

<h3>attr_writerを使う場合</h3>
上記コードから書き込みメソッドの定義を削除し、以下のコードを追加します。

```
attr_writer :name, :age
```

<h3>上記反映後のコード</h3>
次のとおり、非常にスッキリとしました。

```ruby:attr.rb
class User
  attr_writer :name, :age
  attr_reader :name, :age
end

  user = User.new

  user.name = "ruby太郎"
  user.age = 20

  puts "名前:#{user.name}"
  puts "年齢:#{user.age}歳"

```

<h3>attr_accessorを使う場合</h3>
attr_accessorを使うと、読み書きのメソッドが同時に定義できるため、以下のとおりになります。


```ruby:attr.rb
class User
  attr_accessor :name, :age #ここを修正
end

  user = User.new

  user.name = "ruby太郎"
  user.age = 20

  puts "名前:#{user.name}"
  puts "年齢:#{user.age}歳"

```

<h3>attr_reader、attr_writerって必要?</h3>
さて、attr_accessorにより、読み書き同時に定義できるのであれば、attr_reader、attr_writerは必要なのでしょうか?

もちろん、必要です。

試しに、上記コードにinitializeメソッドを追加して初期値を設定してみます。

```ruby:attr.rb
class User
   attr_accessor :name, :age

  def initialize(name:, age:)
    @name = name
    @age = age
  end
end

  user = User.new(name: "ruby太郎", age: 20)

  puts "名前:#{user.name}"
  puts "年齢:#{user.age}歳"

```

このとき、年齢は歳をとれば変わる(上書きが必要)けど、名前は変わらない(上書きが不要)ということであれば、attr_accessorにより、名前の書き込みメソッドも定義しているというのは、予期せぬ動作の原因となります。
つまり、名前については、書き込みメソッドがない(上書きできない)ほうがよいということになります。

であるならば、先程のコードは以下のとおり、書き換えるほうがよいということになります。

```ruby:attr.rb
class User
  attr_reader :name
  attr_accessor :age

  def initialize(name:, age:)
    @name = name
    @age = age
  end
end

  user = User.new(name: "ruby太郎", age: 20)

  puts "名前:#{user.name}"
  puts "年齢:#{user.age}歳"

```

<h1>参考</h1>
https://docs.ruby-lang.org/ja/latest/method/Module/i/attr_reader.html
https://docs.ruby-lang.org/ja/latest/method/Module/i/attr_writer.html
https://docs.ruby-lang.org/ja/latest/method/Module/i/attr_accessor.html


0
0
1

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?