使用 super class 而不是 gem 的克隆方法对 ruby 对象进行深层复制

Making deep copy's of ruby objects using clone method using super class not a gem

我在 ruby class 中尝试实现克隆方法。我希望能够使用所有 classes 都可以继承的通用克隆方法。 class 的属性可以是数组类型、散列或其他一些对象。

我可以使它更通用以便深度克隆吗?可能在 superclass QueryModel 中定义一个克隆方法?那将如何运作?

class Bool < QueryModel

  attr_accessor :name, :should, :must, :must_not

  def clone
    Bool.new(self.name, self.should.clone, self.must.clone, self.must_not.clone) 
  end


  def serialize
      result_hash = {}
      query_hash = {}

      if( instance_variable_defined?(:@should) )
      query_hash[:should] = @should.serialize
      end

      if( instance_variable_defined?(:@must) )
        query_hash[:must] = @must.serialize
      end

      if( instance_variable_defined?(:@must_not) )
        query_hash[:must_not] = @must_not.serialize
      end

      if( instance_variable_defined?(:@should) || instance_variable_defined?(:@must) || instance_variable_defined?(:@must_not) )
        return result_hash = query_hash
    end
  end
end

这里是可以使用克隆的地方:

class Query < QueryModel

  attr_accessor :query_string, :query, :bool

  def serialize 
    result_hash = {}
    query_hash = {}

    if( instance_variable_defined?(:@query_string) )
      query_hash[:query_string] = @query_string.serialize
      #result_hash[:query] = query_hash
    end

    if( instance_variable_defined?(:@query) )
      query_hash[:query] = @query
    end

    if( !instance_variable_defined?(@bool) )
      if( instance_variable_defined?(:@query) || instance_variable_defined?(:@query_string) )
        result_hash[:query] = query_hash
        return result_hash
      end
    else
      bool =  @bool.clone
      result_hash[:query] = bool
    end

  end

end

如果你不怕新宝石,amoeba gem has everything you need for cloning AR objects. If you really only want to copy the objects attribures and not relations, the dup方法就是你要找的。

更新:抱歉,昨天来晚了,我以为您正在以某种方式使用 ActiveRecord。对于您的纯 ruby 解决方案,只需使用 Object#clone 方法而不覆盖并指定 Object#clone 的行为,如下所示:

class Bool
  def initialize_copy(original)
    super # this already clones instance vars that are not objects

    # your custom strategy for 
    # referenced objects can be here

  end
end

这是 docs 对此的评价。

如果您使用 creational/prototype 设计模式解决问题,您可以像下面的示例那样做 -

class ConcretePrototype
  def copy
  prototype = clone

    instance_variables.each do |ivar_name|
      prototype.instance_variable_set( ivar_name,
      instance_variable_get(ivar_name).clone)
    end

    prototype
  end
end

class Application
  def run
    concreate_prototype = ConcretePrototype.new
    concreate_prototype_2 = concreate_prototype.copy
    puts concreate_prototype.inspect
    puts concreate_prototype_2.inspect
  end
end

这样你就可以在没有任何gem的情况下深度克隆对象。 参考 - https://github.com/vatrai/design_patterns/blob/master/creational/prototype.rb