【问题标题】:Making deep copy's of ruby objects using clone method using super class not a gem使用超类而不是 gem 的 clone 方法制作 ruby​​ 对象的深拷贝
【发布时间】:2015-08-03 21:34:06
【问题描述】:

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

我可以让这个更通用,以便深度克隆吗?可能在超类 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

【问题讨论】:

标签: ruby-on-rails ruby ruby-on-rails-4 ruby-on-rails-3.2


【解决方案1】:

如果您使用创建/原型设计模式解决问题,您可以像下面的示例一样 -

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

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

【讨论】:

    【解决方案2】:

    如果您不惧怕新 gem,amoeba gem 拥有克隆 AR 对象所需的一切。如果你真的只想复制对象属性而不是关系,dup 方法就是你要找的。​​p>

    更新:抱歉昨天来晚了,我以为你在使用 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 对此的评价。

    【讨论】:

    • 不想使用其他 gem 来做这件事。需要学习如何在纯红宝石中以正确的方式做到这一点。 dup 将如何帮助?你能举个例子吗?谢谢!
    猜你喜欢
    • 1970-01-01
    • 2013-09-09
    • 1970-01-01
    • 1970-01-01
    • 2018-02-26
    • 2016-09-27
    • 2015-09-14
    • 1970-01-01
    • 2012-06-19
    相关资源
    最近更新 更多