2012-01-14 13 views

答えて

3

Ruby用のC拡張を書く場合、誰かが設定するたびにセッターフックを起動するグローバル変数を実際に作ることができます。

しかし、あなたはCを書く必要があり、それを管理するのが苦痛かもしれないので、おそらくそれをしたくないでしょう。

より良い戦略は、変数が適切な方法で読み込まれ、設定されるようにすることです。その後、setterメソッドが呼び出されると、あなたは何でもできます。ここではオブジェクト内の変数をカプセル化する例を次に示します。

class Foo 
    def bar=(v) 
    @bar = v 
    # do some stuff 
    end 

    def bar 
    @bar 
    end 
end 

同様に、モジュールまたはクラスの代わりに、オブジェクト内の変数をカプセル化することができます。

+0

+1。あなたが書いたCエクステンションの例を指すことができますか? – Swanand

+0

ええ、https://github.com/ruby/ruby/blob/trunk/README.EXTの 'rb_define_hooked_variable'をチェックしてください。 –

1

プリアンブル:これは解決策ではありません(pstは既に書いてあります:ありません)が、特殊な状況で役立つ可能性があります。

私の最初の考えは解決策を得るためにfreezeを使用していた:

module FreezeWarning 
    def freeze 
    puts "#{self}: I am changed" 
    end 
end 

a = "aa" 
a.extend(FreezeWarning) 
a.freeze 
a << 'b' #aa: I am changed 

まず問題:変数の値を変更したときに今、私たちはfreezeを再定義する必要がありますし、私たちはヒントを得る

a = "aa" 
a.freeze 
a << 'b' #can't modify frozen string (RuntimeError) 

を:There is no way to get the variable name

あなたは追加の変数(あなたがあなた自身の変数の識別を定義することができ、それは名前であってはなりません)

module FreezeWarning 
    def change_warning(name) 
    @varname = name 
    self.freeze 
    end 
    def freeze 
    puts "<#{@varname}> (#{self}): I am changed" 
    end 
end 

a = "aa" 
a.extend(FreezeWarning) 
a.change_warning('a') 
a << 'b' #<a> (aa): I am changed 

しかし、より大きな問題でこれを解決する可能性があります、これは、値の変化でのみ動作していません新しい課題:

a = 5 
a.freeze 
a = 4 
p a # -> 4 

これは非常に制限された「解決策」です。

+0

アイデアをありがとう。 – sawa