0
0

More than 1 year has passed since last update.

Rubyのクラスのアクセサについて

Posted at

Rubyのクラスについて、インスタンス変数の参照・代入とそれを可能にするattr_accessorをまとめます。

クラスの基本内容については先日まとめた記事をご確認ください。
selfと@の違い、selfと()の省略についてはこちらの記事をご確認ください。
インスタンスメソッド、クラスメソッド、メソッドの呼び出し制限によるプライベートメソッドについてはこちらの記事をご確認ください。

インスタンス変数に対する読み取りと書き込み

インスタンス変数は直接参照・代入できない

インスタンス変数は、クラスの中では参照(値を取り出す)・代入が可能ですが、クラスの外からは直接参照・代入はできません。
例) インスタンス変数を直接参照・代入するとエラーになる

class S

  def initialize(name="name")
    @name = name
  end

end

s=S.new("aaa")
puts s.@name  #=>syntax error, unexpected tIVAR
puts s.@name="bbb"  #=>syntax error, unexpected tIVAR
puts s.name  #=>NoMethodError
puts s.name="bbb"  #=>NoMethodError

そもそも上記のようなインスタンス名.メソッド名で呼び出すためにはインスタンスメソッドを作成する必要があります。

インスタンス変数を参照・代入するメソッドを作る

インスタンス変数を参照・代入するメソッドは以下のように呼ばれます。

  • ゲッタ:インスタンス変数の値を取り出すメソッド
  • セッタ:オブジェクトのインスタンス変数に値を代入するためのメソッド

例2)インスタンス変数を参照・代入するインスタンスメソッドを作る

class S

  def initialize(name="name")
    @name = name
  end

  # ゲッタ
  def name
    @name
  end

  # セッタ
  def name=(string)
    @name = string
  end

end

s=S.new("aaa")
puts s.name  #=>aaa
puts s.name="bbb"  #=>bbb

ゲッタとセッタを定義することでインスタンスメソッドの参照・代入が可能になりました。しかしインスタンス変数が多くなると、インスタンス変数ごとにゲッタとセッタを定義するのは煩雑になります。
そこで、attrで始まるメソッドを使用します。

attrで始まるメソッド4つ

  • attr_reader
    インスタンス変数の読み取りメソッド(ゲッタ)を定義するメソッドです。インスタンス変数の参照はできても代入はできません。
class S
 attr_reader :name

 def initialize(name="name")
   @name = name
 end
  
end
  
s=S.new("aaa")
puts s.name  #=>aaa
puts s.name="bbb"  #=>NoMethodError

詳しく言うと、attr_readerは上のS自体のインスタンスメソッドではなく、Moduleというクラスのインスタンスメソッドらしいです。
参考:class Module (Ruby 3.1 リファレンスマニュアル)

  • attr_writer
    インスタンス変数の書き込みメソッド(セッタ)を定義するメソッドです。インスタンス変数の参照はできませんが、代入はできます。
class S
  attr_writer :name
  
  def initialize(name="name")
    @name = name
  end
  
end
    
s=S.new("aaa")
puts s.name  #=>NoMethodError
puts s.name="bbb"  #=>bbb
  • attr
    第1引数に指定したインスタンス変数の読み取りのためのインスタンスメソッド(ゲッタ)を定義するメソッドです。第2引数にtrueを指定した場合には書き込みメソッド(セッタ)も同時に定義します。
class S
  attr :name, true

  def initialize(name="name")
    @name = name
  end
  
end
  
s=S.new("aaa")
puts s.name  #=>aaa
puts s.name="bbb"  #=>bbb
class S

  # 第一引数は複数指定できる。
  attr :name, :email
  def initialize(name="name", email="email")
    @name = name
    @email = email
  end

end

s=S.new("aaa", "aaa@email.com")
puts s.name  #=>aaa
puts s.email  #=>aaa@email.com

しかし、このattrメソッドは、第一引数を複数指定することは可能ですが、第一引数を複数指定しかつ第二引数にtrueを指定することができません。

class S

  # 第一引数を複数指定し、第二引数をtrueにしてセッタも定義するよう指定するが、エラーになる
  attr :name, :email, true  #=>TypeError
  def initialize(name="name", email="email@email.com")
    @name = name
    @email = email
  end
  
end
  • attr_accessor
    そこで、attr_accessorの出番です。
    attr_accessorはインスタンス変数に対する読み取りと書き込みのメソッド(ゲッタとセッタ)の両方を定義するインスタンスメソッドです。
    attr_accessorはattr_readerとattr_writerをあわせたようなもの、もしくはattrの第1引数が複数のときも第2引数にtrueを指定できるものです。
class S
  attr_accessor :name, :email 
  
  def initialize(name="name", email="email")
    @name = name
    @email = email
  end

end
      
s=S.new("aaa", "aaa@email.com")
puts s.name  #=>aaa
puts s.name="bbb"  #=>bbb
puts s.email  #=>aaa@email.com
puts s.email="example@email.com"  #=>example@email.com

まとめ

rubyでよく使われるattr_accessorについて説明するために、attr_reader、attre_writer、attrについても言及しながらまとめました。attrについては調べて初めて存在を知りました。また、attr_accessorは特に意識せず便利機能のように使っていましたが、その裏でゲッタとセッタのメソッドが自動で定義され、クラスの外からインスタンス変数の参照や代入ができるようになるということが分かりました。コードを書く際に、その仕組みが何なのかを理解してから使うことを普段から意識したいと感じました。

0
0
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
0
0