使用 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
我在 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