Déclarer des variables d'instance itérant sur un hachage!
-
06-07-2019 - |
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!
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.