2009-02-28 19 views
0

私は本当にRubyを初めて使っています。そして新しく - 16時間未満でしたが、私の上司はRubyのコードを追加しました。しかし、私はそれが1つの巨大なファイルであり、モジュール化されていないことが分かったので、私はそれをきれいにすることに決めました。私はいくつかのファイル/クラス(一般的に言えば、ファイルごとに1つのクラス)に分割してしまったので、それを再び一緒にするために一緒につなぎ合わせるのに問題があります。もともとはすべてが同じクラスに属していたので、呼び出しがうまくいっていましたが、それは醜く見えました。私は、このコードが完了する前にはるかに大きくなるので、これを避けたい。別のクラスの中にあるクラスからインスタンス変数にアクセスするには

私の主な問題は、(明らかに簡略化され、)次のようになります。

class TestDevice 
    def initialize 
    @loghash = { } 
    .... 
    end 
end 

class Log 
    def self.msg(identifier, level, section, message) 
    ... 
    @loghash[identifier] = { level => { section => message }} 
    ... 
    end 
end 

device = TestDevice.new 

はその後、それは他のクラスのメソッドに出て呼び出し、それらのクラスメソッドは、そのログのニーズに合わせてクラスのログに戻って参照します。もちろん、Logはそのハッシュの情報をログするために何らかの形で "device.loghash"にアクセスする必要があります。しかし、私はどのようにして、 "loghash"の内容をすべてのメソッドに渡すことができないのかを理解することができないので、それらを渡すことができ、値を元のポイントに戻してログに記録することができます最後に、それは本当に不器用で厄介なようです。

私は本当に何かが欠けていると思っています。

答えて

4

簡単な方法でインスタンス変数のアクセサを作成するには、attr_accessorを使用します。

class TestDevice 
    attr_accessor :loghash 

    def initialize 
    @loghash = { } 
    .... 
    end 
end 

アクセサーを手動で定義することもできます。

class TestDevice 
    def loghash 
    @loghash 
    end 
    def loghash=(val) 
    @loghash = val 
    end 
end 

これは効果的にattr_accessorの背後で行われます。

+0

「これは実質的にattr_accessorがバックグラウンドで行うこと」です。 –

+0

そうです。それをキャッチするためにありがとう。 – Chuck

2

デバイスオブジェクトをパラメータとしてmsg関数に渡すのはどうですか? (あなたのプログラムには多くのデバイスが存在することが想定されています。そうでなければ、シングルトンパターンを使用できます)。

class TestDevice 
    attr_accessor :loghash 

    def initialize 
    @loghash = { } 
    .... 
    end 
end 

class Log 
    def self.msg(device, identifier, level, section, message) 
    ... 
    device.loghash[identifier] = { level => { section => message }} 
    ... 
    end 
end 
1

ルビースコープのルールを習得する必要があります。

Rubyの変数は、その接頭辞に応じて、異なるスコープを持っている:$

  • $global_variables開始し、誰にでも利用可能です。
  • @instance_variablesは、@で始まり、現在の値はselfです。 2つの スコープ(これらは、例えば、両方のインスタンスメソッドだ)selfの同じ値を共有する場合、 は次に@@と同じインスタンス変数を
  • @@class_variable開始を共有両方、およびクラスに格納されています。それらは、クラスのすべてのインスタンスとそのクラスのサブクラス のすべてのインスタンスの間で共有される です。
  • Constantsは大文字で始まり、すべて大文字でもかまいません。クラス のように、変数は現在のself.classで保存されますが、 も階層をトリクルアップします。したがって、モジュールに定義されているクラスがある場合は、 クラスのインスタンスもモジュールの定数にアクセスできます。 クラスの外部で定義された定数には、グローバルスコープがあります。 定数変数は、どのオブジェクトが定数 にバインドされているかは変わらず、オブジェクト自体が内部状態を変更しないということではありません。小文字

あなたはスコープhereについての詳細を読むことができると

  • local_variablesスタート。ルールをスコープ

    ローカル変数は、主に標準装備されています - 彼らは我々が モジュール、クラス、またはメソッドの定義に移動するとき、1のすべてのサブスコープは、それらがexceptに定義されてい で利用できます。私たちはあなたの 答え

    class TestDevice 
        attr_accessor :loghash 
        def initialize 
        @loghash = { } 
        end 
    end 
    
    device = TestDevice.new 
    
    class Somethingelse 
        def self.something 
        device.loghash='something here' # doesn't work 
        end 
    end 
    

    からあなたのコードを見ればそうトップレベルで定義されたdeviceローカル変数のスコープはSomethingelse.something メソッドの定義が含まれていません。したがって、 Somethingelse.somethingメソッド定義で使用されるローカル変数は、異なる(空の)変数です。スコープがそのように動作するようにするには、定数変数またはグローバル変数を使用する必要があります。

    class TestDevice 
        attr_accessor :loghash 
        def initialize 
        @loghash = { } 
        end 
    end 
    
    DEVICE = TestDevice.new 
    $has_logged = false 
    
    class Somethingelse 
        def self.something 
        DEVICE.loghash='something here' 
        $has_logged = true 
        end 
    end 
    
    p DEVICE.loghash # prints `{}` 
    p $has_logged  # prints `false` 
    Somethingelse.something 
    p DEVICE.loghash # prints `"something here"` 
    p $has_logged  # prints `true` 
    
  • 関連する問題