问题描述
我正在运行一些Ruby代码,该代码每次更改日期时都会对Ruby文件进行评估.在文件中,我有常量定义,例如
I'm running some Ruby code which evals a Ruby file every time its date changes. In the file, I have constant definitions, like
Tau = 2 * Pi
并且,当然,它们使解释器每次都显示不想要的已初始化常量"警告,因此,我希望具有以下功能:
and, of course, they make the interpreter display the unwanted "already initialized constant" warning every time, so, I'd like to have the following functions:
def_if_not_defined(:Tau, 2 * Pi)
redef_without_warning(:Tau, 2 * Pi)
我可以这样写所有常量定义来避免警告:
I could avoid the warning by writing all my constant definitions like this:
Tau = 2 * Pi unless defined?(Tau)
但它不雅且有点潮湿(不是 DRY ).
but it is inelegant and a bit wet (not DRY).
是否有更好的方法def_if_not_defined
?以及如何redef_without_warning
?
Is there a better way to def_if_not_defined
? And how to redef_without_warning
?
-
解决方案要感谢史蒂夫:
Solution thanks to Steve:
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的答案不会产生警告,并且会更好.
This question is old. The above code is only necessary for Ruby 1.8. In Ruby 1.9, P3t3rU5's answer produces no warning and is simply better.
推荐答案
以下模块可能会执行您想要的操作.如果没有,它可能会提供一些指向您解决方案的指针
The following module may do what you want. If not it may provide some pointers to your solution
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结构
Forgive me if i've broken any ruby taboos here as I am still getting my head around some of the Module:Class:Eigenclass structure within Ruby
这篇关于如何在没有警告的情况下重新定义Ruby常量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!