Как переопределить константу Ruby без предупреждения?



я запускаю некоторый код Ruby, который оценивает файл Ruby каждый раз, когда его дата меняется. В файле, у меня есть постоянные определения, как



Tau = 2 * Pi


и, конечно же, они заставляют интерпретатор отображать нежелательное предупреждение "уже инициализированная константа" каждый раз, поэтому я хотел бы иметь следующие функции:



def_if_not_defined(:Tau, 2 * Pi)
redef_without_warning(:Tau, 2 * Pi)


я мог бы избежать предупреждения, написав все мои определения констант следующим образом:



Tau = 2 * Pi unless defined?(Tau)


но это неэлегантно и немного влажной (не сухой).



есть ли лучший способ, чтобы def_if_not_defined? А как же redef_without_warning?



--



решение благодаря Стиву:



class Object
def def_if_not_defined(const, value)
mod = self.is_a?(Module) ? self : self.class
mod.const_set(const, value) unless mod.const_defined?(const)
end

def redef_without_warning(const, value)
mod = self.is_a?(Module) ? self : self.class
mod.send(:remove_const, const) if mod.const_defined?(const)
mod.const_set(const, value)
end
end

A = 1
redef_without_warning :A, 2
fail 'unit test' unless A == 2
module M
B = 10
redef_without_warning :B, 20
end
fail 'unit test' unless M::B == 20


--



этот вопрос старый. Приведенный выше код необходим только для Ruby 1.8. В Ruby 1.9 ответ P3t3rU5 не дает предупреждения и просто лучше.

624   5  

5 ответов:

следующий модуль может делать то, что вы хотите. Если нет, он может предоставить некоторые указатели на ваше решение

module RemovableConstants

  def def_if_not_defined(const, value)
    self.class.const_set(const, value) unless self.class.const_defined?(const)
  end

  def redef_without_warning(const, value)
    self.class.send(:remove_const, const) if self.class.const_defined?(const)
    self.class.const_set(const, value)
  end
end

и в качестве примера его использования

class A
  include RemovableConstants

  def initialize
    def_if_not_defined("Foo", "ABC")
    def_if_not_defined("Bar", "DEF")
  end

  def show_constants
    puts "Foo is #{Foo}"
    puts "Bar is #{Bar}"
  end

  def reload
    redef_without_warning("Foo", "GHI")
    redef_without_warning("Bar", "JKL")
  end

end

a = A.new
a.show_constants
a.reload
a.show_constants

дает следующий результат

Foo is ABC
Bar is DEF
Foo is GHI
Bar is JKL

Простите меня, если я нарушил какие-либо табу ruby здесь, поскольку я все еще получаю свою голову вокруг некоторых из структуры Module:Class:Eigenclass в Ruby

Если вы хотите переопределить значение, то не используйте константы, вместо этого используйте глобальную переменную ($tau = 2 * Pi), но это тоже не очень хорошая практика. Вы должны сделать его переменной экземпляра соответствующего класса.

для другого дела, Tau = 2 * Pi unless defined?(Tau) совершенно хорошо и самый читаемый, поэтому самое элегантное решение.

здесь обсуждается другой подход, использующий $VERBOSE для подавления предупреждений:http://mentalized.net/journal/2010/04/02/suppress_warnings_from_ruby/

если значения констант довольно странно (т. е. у вас есть константы к nil или false), лучшим выбором было бы использовать условный оператор присваивания:Tau ||= 2*Pi

это установит Tau в 2π, если это nil,false или неопределенный, и оставьте его в покое в противном случае.

Как насчет следующего?

TAU ||= 2 * Pi

Он работает на камень, над которым я работаю.

Comments

    Ничего не найдено.