ゲッター・セッター のself

Rubyでメソッド定義していて、self.がつくときがあります。テキトーにやり過ごしていたので、この前「これなんですか?」と質問されてごにょごにょしてしまった。なので調べて備忘録。

 

 self.はクラスメソッドにもつくのですが、今回はそれではなく、セッターとゲッターに付随するselfというものについてまとめます。

 

 まず・・・

 

●ゲッター

 クラス内で定義したインスタンス変数。これはクラス内がスコープ範囲になります。なのでクラス外で呼び出しても参照されません。

 そこで、クラス外でも件のインスタンス変数を呼び出せるようにメソッドとして定義したものを「ゲッター」といいます。

(ゲッターメソッドとは言わないんですね。なんかそんな言い方するのかと勘違いして使っていました。使わないようにしよう。)

class User
  def initialize(name)
    @name = name
  end

  def name #ゲッター
    @name
  end
end

user = User.new("Hoge") 
user.name  #=>"Hoge"

 ※ このuser.nameというような書き方。よく使います。なぜなら普段私たちがRailsで何の気なしにメソッドとして呼び出しているカラム名のメソッドも、Railsが自動で生成してくれたゲッターのメソッドだからです。

 変数として呼び出したインスタンス。DBのカラムからパラメータとして呼び出したインスタンスのデータを、自動でゲッターとして定義してくれています。

 なので「インスタンス.カラム名」と書くだけでデータを呼び出せるのです。

 

●セッター

 ゲッターの時と同様、インスタンス変数はクラス外から更新もできない。それを更新できるようにメソッドとして定義したものを「セッター」という。

class User
  def initialize(name)
    @name = name
  end

  def name=(name) #セッター
    @name = name
  end
end 
user = User.new("Hoge")
user.name =
Gefu #=>"Gefu"

 このようにnewで作ったHogeインスタンスをGefuに変更できました。セッターには「=」をつけるので注意が必要ですね。

 

●attr_accessor

 以前まとめた「あとりびゅーとあくせさー」 ですが、このゲッターとセッターを自動生成してくれる機能です。外部からアクセスできるインスタンス変数を設定するために使います。

 

 

 さて、self.の話でした。

 クラス内のメソッドはゲッターやセッターを利用して、変数を参照したり、更新するものがある。その定義式でゲッターやセッターのメソッドを適用するために擬似変数selfを使う。

 

class User
    attr_accessor :name
  def set_no_name  #セッター
self.name = "名無しさん" if name.nil?
  end

  def say_name  #ゲッター
   p "私は #{self.name} です" #ここでのselfは普通は省略する
   end
end

user = User.new
user.name
#=>"nil"
user.set_no_name #=>"名無しさん"
user.name #=>"名無しさん"
user.say_name #=>"私は 名無しさん です"

 

 このような場合、set_no_nameメソッドを使うと、self.name=でname=メソッド(セッター)が呼ばれて、変数の値が更新される。

 この時、.name=メソッドを適用するインスタンスの「擬似変数」としてselfが参照される。

 ゲッターセッターで定義したインスタンス変数自身(@name)にメソッドを適用するので、何に対してメソッドをつけているか見やすくするためにも擬似変数selfを使うのである。

 

 このようにselfを扱うが、ゲッターとセッターのどちらの利用時にもselfをつけて擬似変数を明確にできる。しかし、ゲッター(変数の参照)ではselfを省略できるが、セッター(変数の更新)では省略してはいけない。というルールがある。

 というのも、セッターを呼んで更新する際に、selfをつけなかったら、ローカル変数として定義しているのか判別がつかない。

  先ほどのセッター呼び出しのメソッドで比べると・・・

  def set_no_name  
   self.name = "名無しさん"
#セッターメソッドのインスタンス変数を再定義
   name = "名無しさん" #ただのローカルメソッドの定義
  end

 

 ゲッターの方はメソッドの呼び出しだから問題なし。ローカル変数との勘違いが起きるとすれば、同一メソッド内にゲッターと同じ名前でローカル変数を定義してしまった時だが、それはその定義の仕方が悪い。

 

 以上

 

 冗長になってしまったので要約

● ゲッター(インスタンス変数の参照)の呼び出しの時にはselfは省略する(=がない時、つまり変数の定義をしてない時)

● セッター(インスタンス変数の更新)の呼び出しの時にはselfは省略してはいけない(=があるとき、つまり変数の定義をしている時)

 

 

<参考URL> ありがとうございました。

https://qiita.com/k-penguin-sato/items/5b75be386be4c55e3abf

https://qiita.com/wonder_meet/items/5fdefca84722fcfcfba8

https://www.te-nu.com/entry/2017/02/26/180550