LoginSignup
0
0

More than 3 years have passed since last update.

rubyで変数を使える範囲【スコープ】

Last updated at Posted at 2020-11-05

変数のスコープについて、かなり単純なコードで説明したいと思う。

下記のようなコントローラーが記述されていたとする。

class SampleController < ApplicationController

  def test1
    sample_1 = 10
    test3(sample_1)
  end 

  def test2
    sample_2 = 10
    test4
  end

  private

  def test3(num)
    sample_3 = num + 10
  end

  def test4
    sample_4 = sample_2 + 10
  end

end

見たところ、test1アクションではプライベートメソッドのtest3(num)アクションを呼び出すことになり、test2アクションではプライベートメソッドのtest4アクションを呼び出すことになる。

結論から先に書くと、test1からのtest3(num)の呼び出しと処理は上手くいくが、test2からのtest4の呼び出しはできるが処理がうまくいかずエラーが出る。

何が違うのか

test1とtest3の場合

test1では、その内部でsample_1 = 10と定義して、それを実引数としてtest3(sample_1)という書き方でtest3(num)に渡している。

  def test1
    sample_1 = 10
    test3(sample_1)
  end

test3内部では、渡されたsample_1が仮引数であるnumに代入される。つまりわかりやすく(?)書くとnum = 10ということになる。

  def test3(num)
    sample_3 = num + 10
  end

こうして無事にnumに数を引き渡せたのでtest3(num)の中身の計算は実質sample_3 = 10 + 10
となって、sample_3 = 20 となる。

test2とtest4の場合

test2では、その内部でsample_2 = 10と定義したあと、test4を呼び出している。

  def test2
    sample_2 = 10
    test4
  end

test4内部では、test2で定義されたsample_2 = 10が使えるので、中身の計算は実質
sample_4 = 10 + 10となるため、sample_4 = 20とな・・・・・・らない。

エラーが出ます

なぜか?

  def test4
    sample_4 = sample_2 + 10
  end

実はtest4内部でsample_2が使えないからである。
いくらtest2内部でsample_2 = 10と定義していようが、test4さんには関係ない事なのである。

これが変数のスコープと呼ばれる物。
結論から先に書けば、test4内部使える変数は

  • test4で定義した変数、または
  • test4を呼び出したtest2内部で定義されたインスタンス変数

なのである。(正確に言えば確かグローバル変数とかいうやつも使えたと思うが話がややこしくなるので省略)

ん?インスタンス変数?あれです、あの@ついたやつです。

というわけで、test4の中でsample_2 = 10を使いたいなら

  def test2
    @sample_2 = 10
    test4
  end

っていう風に定義して、test4でも

  def test4
    sample_4 = @sample_2 + 10
  end

っていう風に@をつけて呼び出してあげれば使うことができ、無事にsample_4 = 20となる。

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