Как узнать, когда переменная экземпляра устанавливается в Ruby - PullRequest
7 голосов
/ 18 апреля 2010

Есть ли способ переопределить установку переменных экземпляра в Ruby?

Допустим, я установил переменную экземпляра:

@foo = "bar"

Могу ли я перехватить это и что-то сделать (например, записать или поставить)

Полагаю, я пытаюсь переопределить оператор присваивания для всех типов. Можно ли это сделать?

Лучшее, что я когда-либо придумал, это:

class Module
  def attr_log_accessor( *symbols )
    symbols.each { | symbol |
      module_eval( "def #{symbol}() @#{symbol}; end" )
      module_eval( "def #{symbol}=(val) 
                      @#{symbol} = val
                      puts \"#{symbol} has changed\"
                    end" )
    }
  end
end

Затем, когда я определяю метод доступа и устанавливаю его, мой код выполняется:

class Test
  attr_log_accessor :foo

  def DoSomething
    self.foo = "bar"
  end
end

К сожалению, для этого требуется, чтобы я написал self.foo = "bar" вместо @foo = "bar".

Есть мысли?

Ответы [ 3 ]

4 голосов
/ 18 апреля 2010

Нет, вы не можете сделать это напрямую. Наилучшим подходом к этому было бы получить доступ к переменным экземпляра только через методы getter / setter и переопределить их.

1 голос
/ 18 апреля 2010

Вы можете возиться с instance_variable_get , instance_variable_set и instance_variables . Более подробную информацию можно найти в этой статье Ruby's Metaprogramming Toolbox .

Если бы вы могли описать, почему вы пытаетесь это сделать, мы могли бы предложить лучший метод.

0 голосов
/ 18 апреля 2010

Вы можете сделать это, используя method_missing()

пример:

def method_missing(name, *args)
  attribute = name.to_s
  if attribute =~ /=$/
    @attributes[attribute.chop] = args[0]
  else
    @attributes[attribute]
  end
end

Если у вас есть обработка в вашем получателе / ​​установщике, этот метод быстро станет раздутым.

Для получения дополнительной информации проверьте исходный код OpenStruct. Также я извлек этот код из Ruby метапрограммирования (стр. 52)

Также обратите внимание, что это отлавливает все недостающие методы. Если вы хотите перехватить только obj.[*]=, вам придется изменить @attributes[attribute] на super

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...