الإعلان عن متغيرات المثيلات التي تتكرر عبر التجزئة!
-
06-07-2019 - |
سؤال
أريد أن أفعل ما يلي:
أريد الإعلان عن متغيرات المثيل لفئة تتكرر عبر القاموس.
لنفترض أن لدي هذا التجزئة
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.