Frage

Ich möchte folgendes tun:

Ich möchte die Instanzvariablen einer Klasse Iterieren über ein Wörterbuch erklären.

Nehmen wir an, dass ich diesen Hash haben

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

, und ich will jede Taste Instanzvariable einer Klasse haben. Ich möchte wissen, ob ich die Variablen über diese Hash-Iteration erklären könnte. So etwas wie folgt aus:

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

Ich weiß, das funktioniert nicht! ich diese nur von Code setzen Stück zu sehen, ob man konnte verstehen, was ich noch deutlicher werden soll.

Danke!

War es hilfreich?

Lösung

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

Die Eigenklasse ein Sonderklasse Gehören nur auf ein einzelnes Objekt, so definierten Methoden geben Instanzmethoden des Objekts sein, aber gehören nicht zu anderen Instanzen des normalen Klasse des Objekts.

Andere Tipps

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

Chuck Antwort ist besser als meine letzten zwei Versuche. Die Eigenklasse ist nicht self.class wie ich gedacht hatte; es dauerte einen besseren Test als ich dies zu realisieren geschrieben hatte.

meinen alten Code verwendet, testete ich in der folgenden Art und Weise und stellte fest, dass die Klasse tatsächlich manipuliert wurde und nicht die Instanz:

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}" }

Der Ausgang war:

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

Das widerlegt eindeutig meine Voraussetzung. Ich entschuldige mich Chuck, Sie waren die ganze Zeit Recht.

ältere Antwort:

attr_accessor funktioniert nur, wenn in einer Klassendefinition ausgewertet, nicht die Initialisierung einer Instanz. Deshalb wollen die einzige Methode, um direkt zu tun, was Sie ist instance_eval mit einem String zu verwenden:

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

Mit diesem Versuch testen:

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

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

  

OpensStructable ist ein mixin Modul   was kann OpenStruct Verhalten liefern   zu jeder Klasse oder Objekt. OpenStructable   ermöglicht Erweiterung von Datenobjekten mit   beliebige Attribute.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top