Как получить доступ к переменным экземпляра из одного класса внутри другого класса - PullRequest
0 голосов
/ 28 февраля 2009

Я действительно новичок в 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» каждому методу, чтобы они, в свою очередь, могли передать его, а затем вернуть значение обратно в точку происхождения и затем зарегистрировать его в конце, но это кажется действительно неуклюжим и неловким.

Я надеюсь, что я действительно что-то упускаю.

Ответы [ 3 ]

4 голосов
/ 28 февраля 2009

Чтобы создать методы доступа для переменных экземпляра простым способом, используйте 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 делает за сценой.

2 голосов
/ 28 февраля 2009

как насчет передачи объекта устройства в качестве параметра функции 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 голос
/ 01 марта 2009

Так что вам нужно выучить правила рубинового обзора.

Переменные Ruby имеют различную область видимости в зависимости от их префикса:

  • $global_variables начинаются с $ и доступны всем.
  • @instance_variables начинаются с одного @ и сохраняются с текущим значением self. Если два области имеют одинаковое значение 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`
...