18
2

More than 1 year has passed since last update.

Tips: Rubyでprivate/protectedなattr_*を宣言する方法

Last updated at Posted at 2022-07-24

これは何

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などは配列を取ることができませんでした。

3.0より前
class Hoge
  private :hoge, :fuga #=> OK
  private [:hoge, :fuga] #=> Error
end

しかし、3.0以降のバージョンでは配列も取れるようになっています。

3.0以降
class Hoge
  private :hoge, :fuga #=> OK
  private [:hoge, :fuga] #=> OK
end

2. attr_*がメソッド名の配列を返すようになった

3.0より前のバージョンのRubyでは、attr_*nilを返していました。

3.0より前
class Hoge
  attr_reader :fuga #=> nil
end

しかし、3.0以降のバージョンでは定義されるメソッド名を返すようになっています。

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の変化

もしよかったら読んでみてください。

18
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
2