まず、この3つのメソッド話題のときに理解していないといけないのはインスタンス変数です。
インスタンス変数とはその名の通り、インスタンスを格納している変数です。(説明になってないので、こちらの記事をご覧ください。)
インスタンス変数というのはクラス外からは参照できないんです。
実際にコードを書いていきます。
class User
def initialize(name)
@name = name
end
end
user = User.new("John")
p user.name
=> NoMethodError (undefined method `name' for #<User:0x00000235aa72df80 @name="John">)
上のコードを見ていただくと分かるのですが、インスタンス変数はクラス外部からは参照できないんです。
attr_reader
そこで、クラス外からインスタンス変数を参照したい時に、読みとり専用のメソッドを定義する必要があります。
class User
def initialize(name)
@name = name
end
def name #読み取り用のメソッド
@name
end
end
user = User.new("John")
p user.name
=> "John"
このように書くことで、Johnという値が出力されました。
でも、この書き方だと参照するインスタンス変数が増えるほど、読み取り専用のメソッドを追加で書いていかなきゃいけないので非常にめんどくさいですね。
そこで登場するのがattr_readerです。前置き長くなってしまいましたね笑
これを使うと、以下のように書けます。
class User
attr_reader :name
def initialize(name)
@name = name
end
end
user = User.new("John")
p user.name
=> "John"
attr_readerはゲッターメソッドを1行で定義できるので、可読性が上がりますね!
attr_writter
ここまで読んだ方で勘の良い方はattr_writterの役割は分かるかもしれませんね。
このメソッドの役割は書き込み専用のメソッドを定義できるというところです。現状だと読み込みはできるのですが、nameの値を変更できないんです。実際にエラーを吐かせてみましょう
class User
attr_reader :name
def initialize(name)
@name = name
end
end
user = User.new("John")
user.name = 'Taro'
=> NoMethodError (undefined method `name=' for #<User:0x00000235aaabdc40 @name="John">)
現状だと値の変更ができないんです。そこで値の書き込み、もっといえば値の変更や作成をする役割を果たすのが、attr_writerです。
実際に書いてみましょう
class User
attr_reader :name
attr_writer :name
def initialize(name)
@name = name
end
end
user = User.new("John")
user.name = 'Taro'
=> "Taro"
上手く動きました!
attr_accessor
今まで紹介してきた、attr_readerとattr_writerの両方をこなすメソッドがattr_accessorです。
「いや、早く言えよ!」って感じですよね笑
2つのメソッドがフュージョンした感じですね
class User
attr_accessor :name
def initialize(name)
@name = name
end
end
user = User.new("John")
user.name = 'Taro'
=> "Taro"
attr_readerは、それだけを使うことでインスタンス変数に格納する値を変えたくないときに使えるかもしれないですね。
以上です。何か間違いがございましたら、ご教示いただけますと幸いです。
【参考資料】