如何在没有警告的情况下重新定义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的答案不会产生任何警告,并且会更好。

4个解决方案
61 votes

以下模块可能会做您想要的。 如果没有,它可能会为您的解决方案提供一些指导

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结构

Steve Weet answered 2019-11-18T04:37:07Z
4 votes

如果要重新定义值,则不要使用常量,而应使用全局变量($ tau = 2 * Pi),但这也不是一个好习惯。 您应该使它成为适当类的实例变量。

在另一种情况下,Tau = 2 * Pi unless defined?(Tau)很好,而且可读性最高,因此也是最优雅的解决方案。

Leventix answered 2019-11-18T04:37:39Z
3 votes

此处讨论了另一种使用$ VERBOSE禁止显示警告的方法:[http://mentalized.net/journal/2010/04/02/suppress_warnings_from_ruby/]

Paul Lynch answered 2019-11-18T04:38:04Z
2 votes

除非常量的值很奇怪(即您将常量设置为nil0或nil065),否则最好的选择是使用条件赋值运算符:nil066

如果将Tau设置为nil0、false或未定义,则将Tau设置为2π,否则将其保留。

Chuck answered 2019-11-18T04:38:38Z
translate from https://stackoverflow.com:/questions/3375360/how-to-redefine-a-ruby-constant-without-warning