読者です 読者をやめる 読者になる 読者になる

メタプログラミング入門(2) ネストしたスコープ

Ruby では,一般的な手続き型言語と違いスコープがネストしません.

var1 = 0

class Hoge
    # var1 は見えない

    var2 = 1

    def huga
        # var1 も var2 も見えない
    end

end

class 内で共有できる変数としてインスタンス変数がありますが,特定のメソッドだけ共有したいなどの要求に答えることはできません.
グローバルスコープについてはグローバル変数がありますが,こちらも細かくスコープを操る事ができません.また,トップレベルオブジェクト(=main)でのインスタンス変数は,self=main のときしか使えないのでクラス定義内では使えないのでこれも微妙です.

解決方法としては,class の代わりに Class.new を,def の代わりに Module#define_method を使います.
このとき与えるブロックは宣言したスコープで束縛されている変数を取り込むので,ネストした変数スコープを実現できます.

var1 = 0

# class の代わりに使う
Hoge = Class.new do
    var1     # => 0     var1 は見える
    
    var2 = 1

    # def の代わりに使う
    define_method :huga do
        var1     # => 0     var1 は見える
        var2     # => 1     var2 は見える
    end

    # var2 を共有したくないメソッド
    def piyo
        var1     # => 0     var1 は見える
        # var2 は見えない
    end

end