その他
    ホーム 技術発信 DoRuby 【Ruby】変数やクラス定義などのスコープ
    【Ruby】変数やクラス定義などのスコープ
     

    【Ruby】変数やクラス定義などのスコープ

    この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

    制御構文ではスコープを作らない(if, while、forなど)

    Rubyではifやwhile、forなどの制御構文ではスコープを作りません。

    if true
      hoge = 'abcd'
    end
    p hoge #=> abcd
    
    for i in 0..5 do
      i += 1
    end
    p i #=> 6
    
    # if, for内で定義された変数は抜けた後も有効
    

    ブロックはスコープを作る(each, map, timesなど)

    each, map, timesなどブロックを引数にとるメソッドでは
    ブロック内でスコープが作られます。

    [0,1,2].each do |i|
      total ||= 0
      total += i
    end
    p total
    NameError: undefined local variable or method `total' for main:Object
            from (irb):2
            from /home/hoge/.rbenv/versions/2.1.8/bin/irb:11:in `<main>'
    

    ブロック内で定義された変数totalには
    外部からアクセスできません。

    ブロック外で定義した変数はブロック内でも有効です。

    total=10
    [0,1,2].each do |i|
      total ||= 0
      total += i
    end
    p total  #=> 13
    

     
    制御構文もdo~endがあってブロックのように見えますが、
    ブロックではないそうです(要調査)
     

    module, class, defもスコープを作る

    module, class, defもスコープを作りますが、少し違います。
    この場合は外部<=>内部のアクセスはどちらもできません。

    num=10
    def fuga
      num ||= 99
    end
    p num   #=> 10
    p fuga  #=> 99
    

    フラットスコープ

    同じクラス/メソッド定義でも、class,defを使うとスコープが作られて、
    Class.newやdefine_methodを使うと作られない、などもあります。

    ▼classで定義した場合は外側で定義したxにアクセスできない

    x = 'XX'
    class Hoge
      def method_x
        x
      end
    end
    Hoge.new.method_x
    NameError: undefined local variable or method `x' for #<Hoge:0x007fe556dbc200>
            from (irb):4:in `method_x'
            from (irb):7
            from /home/hoge/.rbenv/versions/2.1.8/bin/irb:11:in `<main>'
    

    ▼Class.newやdefine_methodを使うと外側の変数にアクセスできる

    x = 'XX'
    y = 'YY'
    Hoge = Class.new() do
      p y  #=> 'YY'
      define_method(:method_x) do
        x
      end
    end
    Hoge.new.method_x  #=> 'XX'
    

    これをフラットスコープといいます。

     
     
     
    「メタプログラミングRuby」に詳しく記載があるので
    とてもおすすめです。
    スコープについての記載がとても興味深かったので、
    もう少し読み解いて理解を深めたいと思います。