ruby克隆对象
我需要克隆一个现有对象并更改该克隆对象。 问题是我的更改更改了原始对象。 代码如下:ruby克隆对象,ruby,class,clone,dup,Ruby,Class,Clone,Dup,我需要克隆一个现有对象并更改该克隆对象。 问题是我的更改更改了原始对象。 代码如下: require "httparty" class Http attr_accessor :options attr_accessor :rescue_response include HTTParty def initialize(options) options[:path] = '/' if options[:path].nil? == true options[:veri
require "httparty"
class Http
attr_accessor :options
attr_accessor :rescue_response
include HTTParty
def initialize(options)
options[:path] = '/' if options[:path].nil? == true
options[:verify] = false
self.options = options
self.rescue_response = {
:code => 500
}
end
def get
self.class.get(self.options[:path], self.options)
end
def post
self.class.post(self.options[:path], self.options)
end
def put
self.class.put(self.options[:path], self.options)
end
def delete
self.class.put(self.options[:path], self.options)
end
end
情景:
test = Http.new({})
test2 = test
test2.options[:path] = "www"
p test2
p test
输出:
#<Http:0x00007fbc958c5bc8 @options={:path=>"www", :verify=>false}, @rescue_response={:code=>500}>
#<Http:0x00007fbc958c5bc8 @options={:path=>"www", :verify=>false}, @rescue_response={:code=>500}>
有办法解决这个问题吗?您需要.clone或者.dup
但这取决于您的目的,但在本例中,您可能需要.clone
看
主要区别在于.clone还复制对象的单例方法和冻结状态
在旁注中,您还可以更改
options[:path] = '/' if options[:path].nil? # you don't need "== true"
你想要.clone或者.dup
但这取决于您的目的,但在本例中,您可能需要.clone
看
主要区别在于.clone还复制对象的单例方法和冻结状态
在旁注中,您还可以更改
options[:path] = '/' if options[:path].nil? # you don't need "== true"
你甚至不需要在这里克隆,你只需要创建一个新的实例 就在这里:
test = Http.new({})
test2 = test
您没有两个Http实例,只有一个。只有两个变量指向同一个实例
你可以改成这个,这样你就不会有问题了
test = Http.new({})
test2 = Http.new({})
但是,如果使用共享选项参数,则会遇到以下问题:
options = { path: nil }
test = Http.new(options)
# options has been mutated, which may be undesirable
puts options[:path] # => "/"
为避免此副作用,您可以将initialize方法更改为使用选项的克隆:
def initialize(options)
options = options.clone
# ... do other stuff
end
您还可以使用splat操作符,它有点神秘,但可能更惯用:
def initialize(**options)
# do stuff with options, no need to clone
end
然后调用构造函数,如下所示:
options = { path: nil }
test = Http.new(**options)
puts test.options[:path] # => "/"
# the original hasn't been mutated
puts options[:path] # => nil
你甚至不需要在这里克隆,你只需要创建一个新的实例 就在这里:
test = Http.new({})
test2 = test
您没有两个Http实例,只有一个。只有两个变量指向同一个实例
你可以改成这个,这样你就不会有问题了
test = Http.new({})
test2 = Http.new({})
但是,如果使用共享选项参数,则会遇到以下问题:
options = { path: nil }
test = Http.new(options)
# options has been mutated, which may be undesirable
puts options[:path] # => "/"
为避免此副作用,您可以将initialize方法更改为使用选项的克隆:
def initialize(options)
options = options.clone
# ... do other stuff
end
您还可以使用splat操作符,它有点神秘,但可能更惯用:
def initialize(**options)
# do stuff with options, no need to clone
end
然后调用构造函数,如下所示:
options = { path: nil }
test = Http.new(**options)
puts test.options[:path] # => "/"
# the original hasn't been mutated
puts options[:path] # => nil
我能问一下你想用这个猴子补丁做什么吗?我正在测试你的代码,但它们似乎不起作用。我能问一下你的猴子补丁到底想做什么吗?我正在尝试测试你的代码,但它们似乎不起作用。这里有好的方面,尽管不清楚OP的最终目的是如何处理这个猴子补丁。我甚至无法让get方法工作。这里有好的方面,尽管还不清楚OP的最终目的是用这个猴子补丁做什么。我甚至无法让get方法发挥作用。