これは何
Rubyにはattr_*
という宣言でインスタンス変数に対するアクセスメソッドを用意することが可能です。
ただ、単純にattr_*
を使ってしまうと、クラス外部にもパブリックな形で公開されてしまいます。
内部だけで参照したい場合でも、アクセスメソッドを用意して変数へのアクセスを厳密に定義したい場合はあると思います。
今回はどうそれを実現するのかを説明します。
バージョン3.0より古いバージョンの場合
実はアクセスメソッドのスコープの絞り方は、3.0以降かそうではないかで書き方が変わります。
まずはバージョン3.0より古いバージョンの場合はどう書くかを説明します。
方法は単純で、private
などの宣言をした後にattr_*
の指定を行えば問題ありません。
以下のようなイメージです。
class Hoge
def initialize
@fuga = 'fuga'
end
private
attr_reader :fuga
end
バージョン3.0以降の場合
バージョン3.0以降の場合、attr_*
の挙動が変わり、よりスタイリッシュな宣言の仕方ができるようになりました。
以下のような書き方ができます。
class Hoge
private attr_reader :fuga
def initialize
@fuga = 'fuga'
end
end
なぜこのような書き方ができるようになったか説明します。
1. private/public/protected
などが、配列も指定できるようになった
3.0より前のバージョンのRubyでは、private
などは配列を取ることができませんでした。
class Hoge
private :hoge, :fuga #=> OK
private [:hoge, :fuga] #=> Error
end
しかし、3.0以降のバージョンでは配列も取れるようになっています。
class Hoge
private :hoge, :fuga #=> OK
private [:hoge, :fuga] #=> OK
end
2. attr_*
がメソッド名の配列を返すようになった
3.0より前のバージョンのRubyでは、attr_*
はnil
を返していました。
class Hoge
attr_reader :fuga #=> nil
end
しかし、3.0以降のバージョンでは定義されるメソッド名を返すようになっています。
class Hoge
attr_accessor :fuga #=> [:fuga, :fuga=]
end
まとめ
1の変化と2の変化によって、3.0以降では以下のような宣言が可能になっています。
class Hoge
private attr_reader :fuga
def initialize
@fuga = 'fuga'
end
end
おまけ
3.0以降の挙動の変化は↓あたりのコードを追うことでわかります。
attr_*
の変化
private/public/protected
の変化
もしよかったら読んでみてください。