アクセサメソッドとは
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で使い分ける感じですかね。


コメント