0

私はRubyを初めて使用します。そして、新しいことによって-16時間未満ですが、上司から追加するRubyコードがいくつか提供されました。しかし、それは1つの巨大なファイルであり、モジュール式ではないことがわかったので、クリーンアップすることにしました。これで、いくつかのファイル/クラス(一般的には、ファイルごとに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

3 に答える 3

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、舞台裏で行っていることです。

于 2009-02-28T08:44:27.997 に答える
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  
于 2009-02-28T10:38:21.470 に答える
2

したがって、ルビスコープのルールを学ぶ必要があります。

Ruby 変数のスコープは、プレフィックスによって異なります。

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

スコープの詳細については、こちらをご覧ください。

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したがって、メソッド定義でdevice使用されるローカル変数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`
于 2009-03-01T16:40:40.153 に答える