Idiomatic object creation in ruby

前端 未结 6 1955
春和景丽
春和景丽 2020-12-01 14:39

In ruby, I often find myself writing the following:

class Foo
  def initialize(bar, baz)
    @bar = bar
    @baz = baz
  end

  << more stuff >>
         


        
6条回答
  •  旧巷少年郎
    2020-12-01 15:21

    Struct

    Struct object's are classes which do almost what you want. The only difference is, the initialize method has nil as default value for all it's arguments. You use it like this

    A= Struct.new(:a, :b, :c)
    

    or

    class A < Struc.new(:a, :b, :c)
    end
    

    Struct has one big drawback. You can not inherit from another class.

    Write your own attribute specifier

    You could write your own method to specify attributes

    def attributes(*attr)
      self.class_eval do
        attr.each { |a| attr_accessor a }
        class_variable_set(:@@attributes, attr)
    
          def self.get_attributes
            class_variable_get(:@@attributes)
          end
    
          def initialize(*vars)
            attr= self.class.get_attributes
            raise ArgumentError unless vars.size == attr.size
            attr.each_with_index { |a, ind| send(:"#{a}=", vars[ind]) }
            super()
          end
      end
    end
    
    class A
    end
    
    class B < A
      attributes :a, :b, :c
    end
    

    Now your class can inherit from other classes. The only drawback here is, you can not get the number of arguments for initialize. This is the same for Struct.

    B.method(:initialize).arity # => -1
    

提交回复
热议问题