سؤال

أريد أن أفعل ما يلي:

أريد الإعلان عن متغيرات المثيل لفئة تتكرر عبر القاموس.

لنفترض أن لدي هذا التجزئة

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

وأريد أن يكون كل مفتاح كمتغير مثيل للفئة.أريد أن أعرف ما إذا كان بإمكاني إعلان تكرار المتغيرات على هذا التجزئة.شيء من هذا القبيل:

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

أعلم أن هذا لا ينجح! لقد وضعت هذا الجزء من الكود فقط لمعرفة ما إذا كان بإمكانك فهم ما أريد بشكل أكثر وضوحًا.

شكرًا!

هل كانت مفيدة؟

المحلول

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

الفئة الذاتية هي فئة خاصة تنتمي إلى كائن واحد فقط، لذا فإن الطرق المحددة ستكون هناك طرق مثيل لذلك الكائن ولكنها لا تنتمي إلى مثيلات أخرى للفئة العادية للكائن.

نصائح أخرى

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

إجابة تشاك أفضل من محاولتي الأخيرتين.الطبقة الذاتية ليست كذلك self.class كما كنت أعتقد.لقد استغرق الأمر اختبارًا أفضل مما كتبته لتحقيق ذلك.

باستخدام الكود القديم، اختبرت بالطريقة التالية ووجدت أنه تم التلاعب بالفصل بالفعل وليس بالمثيل:

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

وكان الإخراج:

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

وهذا يدحض بوضوح افتراضاتي.اعتذاري تشاك، أنت كان الحق طوال الوقت.

الإجابة الأقدم:

attr_accessor يعمل فقط عند تقييمه في تعريف فئة، وليس عند تهيئة مثيل.لذلك، فإن الطريقة الوحيدة للقيام بما تريده مباشرة هي الاستخدام instance_eval مع سلسلة:

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

لاختبار هذه المحاولة:

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

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

OpensStructable is a mixin module which can provide OpenStruct behavior to any class or object. OpenStructable allows extention of data objects with arbitrary attributes.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top