これらはインスタンス変数のgetterおよび/またはsetterメソッドを自動的に生成するRubyのメソッドで、定型コードを排除します。インスタンス変数(@name)は非公開であり外部から直接アクセスできないため、それらを読み書きするにはアクセサメソッドが必要で、attr_*がこれらを簡潔に生成します。
これらが解決する問題
()
= name
()
= value
class Person
attr_reader :name # generates a GETTER only (read-only): person.name
attr_writer :email # generates a SETTER only (write-only): person.email = ...
attr_accessor :age # generates BOTH getter and setter: person.age / person.age = ...
def initialize(name, age)
@name = name
@age = age
end
end
person = Person.new("Ann", 30)
person.name # "Ann" — reader
person.age = 31 # writer
person.age # 31 — reader
person.name = "X" # ❌ NoMethodError — name is read-only (attr_reader, no setter)
attr_reader → getterのみ(読み取り専用アクセス)。attr_writer → setterのみ(書き込み専用)。attr_accessor → getterとsetterの両方(読み書き可能)。それぞれインスタンス変数を表すシンボルを受け取り、対応するメソッドを自動的に生成します。1行で複数の手書きメソッド定義を置き換えられます。
class BankAccount
attr_reader :balance # ✅ balance is readable but NOT directly settable (protect it)
def initialize
@balance = 0
end
def deposit(amount) # changes go through a controlled method, not a raw setter
@balance += amount if amount > 0
end
end
外部から任意に設定されるべきでないフィールドに対して(attr_accessorではなく)attr_readerを選ぶことは、良いカプセル化です。意図したアクセスのみを公開できます。
attr_accessor/attr_reader/attr_writerを理解することは、ほぼすべてのRubyクラスに登場するため、日常的に欠かせないRubyの基礎知識です。
これらが存在する根本的な理由は、インスタンス変数(@name)が非公開でオブジェクトの外部から直接アクセスできないため、それらを読み書きするにはアクセサメソッドが必要であり、すべての属性についてgetter/setterを手書きするのは面倒な定型作業だからです。
これらのメソッドはアクセサを自動的に生成し(attr_readerは読み取り専用、attr_writerは書き込み専用、attr_accessorは両方)、複数のメソッド定義を1行の簡潔な記述に置き換えます。これはRubyの優雅さと簡潔さを象徴するものです。
それぞれが何を生成するかを理解し、適切なものを選ぶことは、良いカプセル化の問題でもあります。外部から任意に設定されるべきでないフィールドにはattr_reader(読み取り専用)を使い、読み書きアクセスが本当に意図されている場合のみattr_accessorを使うことで、オブジェクトの状態がどのように公開されるかを制御できます(例えば、銀行残高を読み取り可能にしつつ制御されたメソッドを通じてのみ変更可能にする)。
これらのアクセサはRubyクラス(およびRailsモデル)で広く使われているため、それらの動作、それぞれが何を生成するか、適切なカプセル化のためにどう選ぶかを知ることは、Rubyクラスを書き読むうえで必須の知識です。Rubyクラスを定義する際に最初に出会うものの一つであり、よくあるニーズ(オブジェクトの状態への制御されたアクセス)に対するこの言語の簡潔で表現力豊かなアプローチを反映しています。
ジュニアからシニアまで、詳細な回答付きのIT面接質問ライブラリ。
寄付する