这个练习有点问题,你能帮助我吗?我试图编辑一个脚本,但每次创建新实例时,最后一个元素都会覆盖其他元素(即)
该类必须为后续块的组合提供功能:即它必须能够从前一个块继承尚未明确定义当前块的指令。
blocks = []
blocks << Block.new({ X:0, Y:100, Z:20}) # p blocks:({ X:0, Y:100, Z:20})
blocks << Block.new({X:100}, blocks[-1]) #p blocks:({ X:100, Y:100, Z:20},{ X:100, Y:100, Z:20})
blocks << Block.new({Y:0}, blocks[-1]) #p blocks:({ X:100, Y:0, Z:20},{ X:100, Y:0, Z:20},{ X:100, Y:0, Z:20})
我遇到问题的代码是:
#!/usr/bin/env ruby
class Block
$instance_2 = true
$instance_3 = true
attr_reader :out
def initialize(out, previous = nil )
@out = update(out, previous)
end # end initialize
def update(actual, previous)
puts "IN UPDATE: box is: #{previous}"
box = previous
if box != nil
puts "IF: changing is: #{actual}"
actual.each do |key, value|
box[key] = value
end
box
else
puts "ELSE"
actual
end # end if
end # end update
def inspect
@out
end
end # end Block
blocks = []
puts "\n#----------------------1 INSTANCE----------------------#"
blocks << Block.new({G: "00", X: 100, Y:100, Z: 100})
puts "\n#----------------------blocks element----------------------#"
p blocks
puts "last block is: #{blocks[-1].out}"
puts "\n#----------------------2 INSTANCE----------------------#" if $instance_2
blocks << Block.new({G: "01"}, blocks[-1].out) if $instance_2
puts "\n#----------------------blocks element----------------------#"if $instance_2
p blocks if $instance_2
puts "last block is: #{blocks[-1].out}"
puts "\n#----------------------3 INSTANCE----------------------#" if $instance_3
blocks << Block.new({G: "02"}, blocks[-1].out) if $instance_3
puts "\n#----------------------blocks element----------------------#" if $instance_3
p blocks if $instance_3
puts "last block is: #{blocks[-1].out}"
puts "\n#----------------------4 INSTANCE----------------------#" if $instance_3
blocks << Block.new({G: "03"}, blocks[-1].out) if $instance_3
puts "\n#----------------------blocks element----------------------#" if $instance_3
p blocks if $instance_3
puts "last block is: #{blocks[-1].out}"
答案 0 :(得分:2)
问题并不完全清楚,但如果我理解正确,可以提供一个可以接受或不接受前一个Block的类。你怎么看待这样的事情?
#!/usr/bin/env ruby
class Block < Hash
def initialize(h, b=nil)
[:x, :y, :z].each do |s|
# We start by trying to assign the coordinate that is in the
# input hash
if h[s]
self[s] = h[s]
else
# If the coordinate is not in h, we check for it in b, but we have to
# remember that if the block that we are providing in b does not have
# the method :[] or the coordinate is nil we may raise an exception
begin
self[s] = b[s]
raise if not self[s]
rescue
raise(Exception, "Cannot initialize block.")
end
end
end
end
def inspect
"block:(x: #{self[:x]}, y: #{self[:y]}, z: #{self[:z]}"
end
end
# Let's try it!
blocks = []
blocks << Block.new({ x:0, y:100, z:20})
puts blocks
puts
blocks << Block.new({x:100}, blocks[-1])
puts blocks
puts
blocks << Block.new({y:0}, blocks[-1])
puts blocks
puts
我们只考虑更新方法:
def update(actual, previous)
puts "IN UPDATE: box is: #{previous}"
box = previous # ! ! ! ! ! ! ! ! WHOOPS!
if box != nil
puts "IF: changing is: #{actual}"
actual.each do |key, value|
box[key] = value
end
box
else
puts "ELSE"
actual
end # end if
end # end update
&#34;呐喊&#34; line就是为你创造问题的原因。有了那条线
您将previous
(您的对象变量实际包含引用)的引用提供给box
变量。当您对box
执行某些操作时,您实际正在做的是修改两个变量指向的内容。
你可以测试我立刻说的话。尝试以这种方式修改该行:
box = previous.clone if previous
(nil
没有#clone
背后的基本原理if
。如果再次运行它,您将获得一个未被修改的块列表。这不是一个有效的代码,你应该重新考虑update
方法代码。