はじめに
インスタンス変数へのアクセサメソッド(読み書きのためのメソッド)について、学んだことをまとめます。 「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