Question

je veux faire ce qui suit:

Je souhaite déclarer les variables d'instance d'une classe itérant sur un dictionnaire.

Supposons que j'ai ce hachage

hash = {"key1" => "value1","key2" => "value2","key3" => "value3"}

et je veux avoir chaque clé comme variable d’instance d’une classe. Je veux savoir si je pourrais déclarer les variables itératives sur ce hachage. Quelque chose comme ça:

class MyClass
  def initialize()
    hash = {"key1" => "value1","key2" => "value2","key3" => "value3"}
    hash.each do |k,v|
      @k = v
    end
  end
end

Je sais que cela ne fonctionne pas! Je mets uniquement ce code pour voir si vous pouvez comprendre plus clairement ce que je veux.

Merci!

Était-ce utile?

La solution

class MyClass
  def initialize()
    hash = {"key1" => "value1","key2" => "value2","key3" => "value3"}
    hash.each do |k,v|
      instance_variable_set("@#{k}",v)
      # if you want accessors:
      eigenclass = class<<self; self; end
      eigenclass.class_eval do
        attr_accessor k
      end
    end
  end
end

eigenclass est une classe spéciale appartenant à un seul objet. Par conséquent, les méthodes définies incluent des méthodes d'instance pour cet objet, mais n'appartiennent pas à d'autres instances de la classe normale de l'objet.

Autres conseils

class MyClass
  def initialize
    # define a hash and then
    hash.each do |k,v|
      # attr_accessor k # optional
      instance_variable_set(:"@#{k}", v)
    end
  end
end

La réponse de Chuck est meilleure que mes deux dernières tentatives. La classe propre n'est pas self.class comme je le pensais; il a fallu un meilleur test que ce que j’avais écrit pour m'en rendre compte.

En utilisant mon ancien code, j'ai testé de la manière suivante et constaté que la classe était bien manipulée et non l'instance:

a = MyClass.new :my_attr => 3
b = MyClass.new :my_other_attr => 4

puts "Common methods between a & b:"
c = (a.public_methods | b.public_methods).select { |v| a.respond_to?(v) && b.respond_to?(v) && !Object.respond_to?(v) }
c.each { |v| puts "    #{v}" }

Le résultat était:

Common methods between a & b:
    my_other_attr=
    my_attr
    my_attr=
    my_other_attr

Ceci réfute clairement mon présupposé. Toutes mes excuses, Chuck, vous avez toujours raison.

Réponse précédente:

attr_accessor ne fonctionne que lorsqu'il est évalué dans une définition de classe, pas l'initialisation d'une instance. Par conséquent, la seule méthode permettant de faire ce que vous voulez est d'utiliser instance_eval avec une chaîne:

class MyClass
  def initialize(params)
    #hash = {"key1" => "value1","key2" => "value2","key3" => "value3"}
    params.each do |k,v|
      instance_variable_set("@#{k}", v)
      instance_eval %{
        def #{k}
          instance_variable_get("@#{k}")
        end
        def #{k}= (new_val)
          instance_variable_set("@#{k}", new_val)
        end
      }
    end
  end
end

Pour tester cet essai:

c = MyClass.new :my_var => 1
puts c.my_var

http://facets.rubyforge.org/apidoc/api /more/classes/OpenStructable.html

  

OpensStructable est un module de mixage   qui peut fournir un comportement OpenStruct   à n'importe quelle classe ou objet. OpenStructable   permet l'extension des objets de données avec   attributs arbitraires.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top