66 votes

Comment redéfinir une constante Ruby sans prévenir?

Je suis en cours d'exécution du code Ruby qui est évaluée comme un Rubis fichier à chaque fois que ses changements de date. Dans le fichier, j'ai des définitions de constantes, comme

Tau = 2 * Pi

et, bien sûr, ils font l'interprète afficher les indésirables "déjà initialisé constante" d'avertissement à chaque fois, donc, j'aimerais avoir les fonctions suivantes:

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

J'ai pu éviter l'avertissement par écrit tous mes définitions de constantes comme ceci:

Tau = 2 * Pi unless defined?(Tau)

mais il est inélégant et un peu humide (pas SEC).

Est-il une meilleure façon d' def_if_not_defined? Et comment redef_without_warning?

--

Solution grâce à 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

--

Cette question est ancienne. Le code ci-dessus est seulement nécessaire pour Ruby 1.8. En Ruby 1.9, P3t3rU5 la réponse de produit sans avertissement et est tout simplement mieux.

73voto

Steve Weet Points 15395

Le module suivant peut faire ce que vous voulez. Dans le cas contraire, cela peut fournir des indications sur votre 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
 

Et comme exemple d'utilisation

 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
 

Donne la sortie suivante

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

Pardonnez-moi si j’ai brisé des tabous concernant le rubis ici, car je suis encore en train de comprendre certains des modules: Classe: Structure de classe propre dans Ruby

8voto

P3t3rU5 Points 61

Qu'en est-il de ce qui suit?

 TAU ||= 2 * Pi
 

Cela fonctionne sur un joyau sur lequel je travaille.

6voto

Paul Lynch Points 185

Une autre approche, utilisant $ VERBOSE, pour supprimer les avertissements, est décrite ici: http://mentalized.net/journal/2010/04/02/suppress_warnings_from_ruby/

4voto

Leventix Points 2310

Si vous voulez redéfinir une valeur, n'utilisez pas de constantes, utilisez plutôt une variable globale ($ tau = 2 * Pi), mais ce n'est pas non plus une bonne pratique. Vous devriez en faire une variable d'instance d'une classe appropriée.

Dans l’autre cas, Tau = 2 * Pi unless defined?(Tau) est parfaitement correct et le plus lisible, donc la solution la plus élégante.

2voto

Chuck Points 138930

À moins que les valeurs des constantes ne soient assez étranges (c’est-à-dire que les constantes soient définies sur nil ou false ), le meilleur choix serait d’utiliser l’opérateur d’affectation conditionnelle: Tau ||= 2*Pi

Ceci fixera Tau à 2π s'il est nil , false ou non défini, et le laissera tranquille sinon.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X