如何在没有警告的情况下重新定义Ruby常量? [英] How to redefine a Ruby constant without warning?

查看:97
本文介绍了如何在没有警告的情况下重新定义Ruby常量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在运行一些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常量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆