In Ruby, can one object destroy another?
For example:
class Creature
def initialize
@energy = 1
end
attr_accessor :energy
end
class Crocodile < Creature
def eat(creature)
@energy += creature.energy
creature = nil #this does not work
end
end
fish = Creature.new
croc = Crocodile.new
croc.eat(fish)
After the crocodile has eaten a creature and absorbed its energy, the creature should cease to exist. But the code above doesn't destroy the creature.
I know that if I say fish = nil
, the object that the varible fish
refers to will be garbage collected. But saying creature = nil
inside the Crocodile's eat
method doesn't accomplish that.
Another way of putting it
From inside croc.eat, can I say "since the variable 'fish' was passed to me, when I'm done, I'm going to set 'fish' to nil?"
Update: problem solved
I've essentially taken the approach that Chuck suggested, with some modifications. Here was my reasoning:
- If there is no longer any variable pointing to an object, it will be garbage collected
- If, when an object is created, I add it to a hash (like 'x' => object), and don't create any other variable for it, then deleting that item from the hash results in garbage collecting the object
- It seems logical that a list of all creatures should be stored in the Creature class
Therefore, I did this:
- On the Creature class object, I created a hash and assigned it to an instance variable. We'll call it
@creaturelist
. (The reason I used an instance variable and not a class variable is so that any subclass ofCreature
can have its own list, too.) - In the Initialize method, a new creature hands itself to the Creature class
- The Creature class adds a reference to that creature to
@creaturelist
and returns an ID to the creature. - The creature remembers that ID in its own
@id
variable. - If the creature dies, it calls the parent class with
Creature.remove(@id)
, and the only reference to itself gets deleted.
Now I can do this:
class Predator < Creature
def eat(creature)
@energy += creature.energy
creature.die
end
end
fish = Creature.new
Creature.list #shows the fish
croc = Predator.new
croc.eat(fish)
Creature.list #no more fish
Of course, in this example, fish
still points to that creature object, so it's not garbage collected. But eventually, creatures will be created and eat each other based on rules, so I won't be individually naming them.