【问题标题】:How to access instance variables from one class while inside another class如何在另一个类中访问一个类中的实例变量
【发布时间】:2009-02-28 08:26:16
【问题描述】:

我对 Ruby 真的很陌生。和新的 - 不到 16 小时,但我的老板给了我一些 Ruby 代码来添加。但是,我发现它是一个巨大的文件,根本不是模块化的,所以我决定清理它。现在我已经将它分解为几个文件/类(一般来说,每个文件 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 以满足它们的日志记录需求。当然,Log 需要以某种方式访问​​“device.loghash”以在该哈希中记录信息。但是我不知道如何在将“loghash”的内容传递给每个方法之外实现这一点,以便他们反过来可以传递它,然后将值返回到起始点,然后记录它最后,但这似乎真的很笨拙和尴尬。

我希望我真的只是错过了一些东西。

【问题讨论】:

    标签: ruby instance-variables


    【解决方案1】:

    要以简单的方式为实例变量创建访问器,请使用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 在幕后所做的。

    【讨论】:

    • 应该是“这实际上是 attr_accessor 在幕后所做的。”
    • 没错。感谢您了解这一点。
    【解决方案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  
    

    【讨论】:

      【解决方案3】:

      所以你需要学习 ruby​​ 作用域的规则。

      Ruby 变量有不同的作用域,取决于它们的前缀:

      • $global_variables$ 开头,所有人都可以使用。
      • @instance_variables 以单个 @ 开头,并与 self 的当前值一起存储。如果两个 范围共享 self 的相同值(例如,它们都是实例方法), 那么两者共享相同的实例变量
      • @@class_variable@@ 开头,并与类一起存储。他们是 在类的所有实例和子类的所有实例之间共享 那个班级的。
      • Constants 以大写字母开头,并且可能全部大写。喜欢上课 变量,它们与当前的self.class 一起存储,但它们也 涓涓细流 - 所以如果你在模块中定义了一个类, 类的实例也可以访问模块的常量。 在类之外定义的常量具有全局范围。 请注意,常量变量意味着哪个对象绑定到常量 不会改变,并不是说对象本身不会改变内部状态。
      • local_variables 以小写字母开头

      您可以阅读有关范围here 的更多信息。

      局部变量范围规则主要是标准的 - 它们在 当我们进入时,它们被定义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 方法定义中使用的device 局部变量是一个不同的(空)变量。如果您希望范围以这种方式工作,您应该使用常量或全局变量。

      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`
      

      【讨论】:

        猜你喜欢
        • 2013-03-24
        • 2020-04-14
        • 1970-01-01
        • 2013-04-16
        • 2018-04-09
        • 2012-05-21
        • 1970-01-01
        • 2011-04-28
        相关资源
        最近更新 更多