Reputation: 51
I have a little problem with this exercise, can you help me? I tried to edit a script, but for each time that I create new instance the last element overwrites the Others (i.e. )
The class must provide a functionality for the combination of consequent blocks: i.e. it must be able to inherit from the previous block the instructions that have not been explicitly defined for the current block.
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})
My code with problems is:
#!/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}"
Upvotes: 3
Views: 170
Reputation: 2956
The question is not exactly clear, but if I understand it correctly it is possible to provide a class that may or not accept a previous Block. What do you think of something like that?
#!/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
Let's consider only the update method:
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
the "whoops" line is what is creating you the issue. With that line
you are giving the reference to previous
(your object variable actually contains a reference) to the box
variable. What you are actually doing, when you perform some action on box
, is modifying what is pointed by both variable.
You can test what I'm saying immediately. Try to modify that line in this way:
box = previous.clone if previous
(nil
does not have a method #clone
that the rationale behind the if
). If you run it again you will get a list of blocks that have not being modified. This is not an efficient code tough, and you should really rethink the update
method code.
Upvotes: 2