【Ruby】attr_accessor とは? attr_reader/attr_writerとの違い

Ruby

アクセサメソッドとは

Rubyではオブジェクトの外部からインスタンス変数を直接参照することができないため、外部から値を参照したいときはメソッド経由にしないといけません。外部から値を使うときの「読み取り用(getter)」「書込み用(setter)」のメソッドを、まとめてアクセサメソッド(アクセスメソッド)といいます。

エラーになる例

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

obj = Obj.new('zima')
p obj.name

上記のように書いた場合、エラーとなります。

practice.rb:8:in `<main>': undefined method `name' for #<Obj:0x000002f4477029f0 @name="zima"> (NoMethodError)

p obj.name
     ^^^^^

ではどのように書けばよいか。

attr_reader(読み取り)

class Obj
  attr_reader :name
  
  def initialize(name)
    @name = name
  end
end

obj = Obj.new('zima')
p obj.name

先ほどエラーになったコードに、 attr_reader :nameを追加しました。
 attr_reader :nameを書くと、nameというgetterが自動で定義されます。

attr_writer(書き込み)

class Obj
  attr_writer :name

  def initialize(name)
    @name = name
  end
end

obj = Obj.new('zima')
obj.name = 'zimaaaa'

attr_writer :nameと書くと、今度はnameというsetterが自動で定義されます。

attr_accessor(読み取り + 書き込み)

class Obj
  attr_accessor :name

  def initialize(name)
    @name = name
  end
end

obj = Obj.new('zima')
obj.name = 'zimaaaa'

p obj.name

attr_accessorはreaderとwriterの両方をまとめて定義してくます。
一つ上のattr_writerを使っているコードでは、getterが無いためp obj.nameのところでエラーとなりますが、attr_accessorにすればエラーにはなりません。

【ちなみに】アクセサメソッドを使わずに書くと?

ちなみにですが、アクセサメソッドを使わずに書くとこんな感じです。この例ではインスタンス変数が一つしかないですが、インスタンス変数が増えればその数だけsetterやgetterを追加しなければなりません。

class Obj

  def initialize(name)
    @name = name
  end

  def name
    @name
  end

  def name=(value)
    @name = value
  end
  
end

まとめ

基本的に公開は必要最小限にして、読み取りだけならattr_reader。
更新も必要ならattr_accessorで使い分ける感じですかね。

コメント

タイトルとURLをコピーしました