İşte bunu nasıl yapabileceğiniz. initialize
parametresinin her biri için @
ile aynı ada sahip değişken ile bir örnek değişkeni ve ilişkili bir okuma/yazma erişimi oluşturulacak ve her bir değişkene ilgili parametrenin değeri atanacaktır.
Kod
class MyClass
def initialize(< arbitrary parameters >)
self.class.params.each { |v|
instance_variable_set("@#{v}", instance_eval("#{v}")) }
< other code >
end
@params = instance_method(:initialize).parameters.map(&:last)
@params.each { |p| instance_eval("attr_accessor :#{p}") }
class << self
attr_reader :params
end
< other code >
end
Örnek
class MyClass
def initialize(a, b, c)
self.class.params.each { |v|
instance_variable_set("@#{v}", instance_eval("#{v}")) }
end
@params = instance_method(:initialize).parameters.map(&:last)
@params.each { |p| instance_eval("attr_accessor :#{p}") }
class << self
attr_reader :params
end
end
MyClass.methods(false)
#=> [:params]
MyClass.instance_methods(false)
#=> [:a, :a=, :b, :b=, :c, :c=]
m = MyClass.new(1,2,3)
m.a #=> 1
m.b #=> 2
m.C#=> 3
m.a = 4
m.a #=> 4
açıklama
sınıfı MyClass
ayrıştırılır, sınıf örneği değişken @params
atanmış olan bir elemanları, initialize
parametresidir. Bu @params = ...
başlayan kod ayrıştırıldığında yöntem initialize
oluşturulduğundan, bu mümkündür.
Method#parameters yöntemi initialize
parametresinin elde edilmesinde kullanılır. Yukarıdaki Örneğin,
instance_method(:initialize).parameters
#=> [[:req, :a], [:req, :b], [:req, :c]]
yüzden
@params = instance_method(:initialize).parameters.map(&:last)
#=> [:a, :b, :c]
Sonra okuma/yazma erişenleri oluşturmak
: initialize
tarafından kullanılmak üzere
@params.each { |p| instance_eval("attr_accessor :#{p}") }
ve @params
için okundu erişimcisi,:
class << self
attr_reader :params
end
MyClass
örneğinin my_class
örneği oluşturulduğunda, MyClass.new
'a iletilen parametre değerleri initialize
'a geçirilir. initialize
, sınıf örneği @params
değişkenine rağmen döngüler yapar ve her örnek değişkenin değerini ayarlar.Bu örnekte,
MyClass.new(1,2,3)
çağırır
a => 1
b => 2
c => 3
Biz initialize(a,b,c)
:
params
(
:a
) birinci elemanı için
params = self.class.params
#=> [:a, :b, :c]
params.each { |v| instance_variable_set("@#{v}", instance_eval("#{v}")) }
, bu:
instance_variable_set("@a", instance_eval(a) }
olduğu:
instance_variable_set("@a", 1 }
@a
neden 1
atanacak.
Not @params
için erişimci gerekli değildir:
class MyClass
def initialize(a, b, c)
self.class.instance_variable_get(:@params).each { |v|
instance_variable_set("@#{v}", instance_eval("#{v}")) }
end
@params = instance_method(:initialize).parameters.map(&:last)
@params.each { |p| instance_eval("attr_accessor :#{p}") }
end
Bu konu hakkında oldukça iyi bir konu. http://stackoverflow.com/questions/2680523/dry-ruby-initialization-with-hash-argument – Jazzepi
@Jazzepi, bu ilginç bir iş parçacığı, ancak yalnızca karma tartışmalarla ilgilidir. –