SORU
21 NİSAN 2010, ÇARŞAMBA


KURU Ruby Hash Değişken ile Başlatma

Son kullanıcı için kullandığı API yapılandırma ya da diğer bit için Dolaylı yazma özellikle yapıcılarına karma argümanlar biraz sonra iki tane daha,. Ne ben ne sonu aşağıdaki gibi olur:

class Example

    PROPERTIES = [:name, :age]

    PROPERTIES.each { |p| attr_reader p }

    def initialize(args)
        PROPERTIES.each do |p|
            self.instance_variable_set "@#{p}", args[p] if not args[p].nil?
        end
    end

end

Daha deyimsel bir şekilde bunu başarmak için var mı? -Atın sürekli ve dize dönüştürmesi için sembolü özellikle korkunç görünüyor.

CEVAP
21 NİSAN 2010, ÇARŞAMBA


Sürekli ihtiyacın yok, ama sembol-dize ortadan kaldırabilirsiniz sanmıyorum:

class Example
  attr_reader :name, :age

  def initialize args
    args.each do |k,v|
      instance_variable_set("@#{k}", v) unless v.nil?
    end
  end
end
#=> nil
e1 = Example.new :name => 'foo', :age => 33
#=> #<Example:0x3f9a1c @name="foo", @age=33>
e2 = Example.new :name => 'bar'
#=> #<Example:0x3eb15c @name="bar">
e1.name
#=> "foo"
e1.age
#=> 33
e2.name
#=> "bar"
e2.age
#=> nil

BTW, olabilir bak (henüz) Struct sınıf jeneratör sınıfı, biraz benzer ne yapıyorsun, ama karma-tip başlatma (ama sanırım olmaz sabit yapmak için yeterli jeneratör sınıfı).

HasProperties

Hurikhan fikri uygulamak için çalışıyor, Bunun için geldim

module HasProperties
  attr_accessor :props

  def has_properties *args
    @props = args
    instance_eval { attr_reader *args }
  end

  def self.included base
    base.extend self
  end

  def initialize(args)
    args.each {|k,v|
      instance_variable_set "@#{k}", v if self.class.props.member?(k)
    } if args.is_a? Hash
  end
end

class Example
  include HasProperties

  has_properties :foo, :bar

  # you'll have to call super if you want custom constructor
  def initialize args
    super
    puts 'init example'
  end
end

e = Example.new :foo => 'asd', :bar => 23
p e.foo
#=> "asd"
p e.bar
#=> 23

Metaprogramming ile yetkin değilim, cevap topluluk kimseye uygulanmasını değiştirmek için ücretsiz yüzden wiki yaptım.

Struct.hash_initialized

Marc-Andre cevabı üzerine genişletilmesi, burada karma başlatıldı sınıfları oluşturmak için genel, Struct tabanlı bir yöntem:

class Struct
  def self.hash_initialized *params
    klass = Class.new(self.new(*params))

    klass.class_eval do
      define_method(:initialize) do |h|
        super(*h.values_at(*params))
      end
    end
    klass
  end
end

# create class and give it a list of properties
MyClass = Struct.hash_initialized :name, :age

# initialize an instance with a hash
m = MyClass.new :name => 'asd', :age => 32
p m
#=>#<struct MyClass name="asd", age=32>

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Glyn Dewis

    Glyn Dewis

    25 AĞUSTOS 2007
  • TantalizingTrance

    TantalizingT

    15 ŞUBAT 2009
  • TomSka

    TomSka

    30 Mayıs 2006