在
Ruby中,一个对象可以破坏另一个吗?
例如:
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)
在鳄鱼吃掉一个生物并吸收其能量后,该生物应该不再存在.但是上面的代码并没有破坏这个生物.
我知道,如果我说fish = nil,变量鱼所指的物体将被垃圾收集.但是在鳄鱼的吃法中说生物=零是不能实现的.
另一种方式
从croc.eat里面,我可以说“因为变量’鱼’被传递给我,当我完成后,我要把’鱼’设置为零?”
更新:问题解决了
我基本上采取了Chuck建议的方法,并进行了一些修改.这是我的推理:
>如果不再有任何指向对象的变量,它将被垃圾收集
>如果在创建对象时,我将其添加到散列(如’x’=>对象),并且不为其创建任何其他变量,然后从散列中删除该项导致垃圾收集对象
>似乎合乎逻辑的是,所有生物的列表都应该存储在Creature类中
因此,我这样做了:
>在Creature类对象上,我创建了一个哈希并将其分配给一个实例变量.我们称之为@creaturelist. (我使用实例变量而不是类变量的原因是,任何Creature的子类也可以拥有自己的列表.)
>在Initialize方法中,一个新生物将自己交给Creature类
> Creature类将对该生物的引用添加到@creaturelist并返回该生物的ID.
>该生物在其自己的@id变量中记住该ID.
>如果生物死亡,它会使用Creature.remove(@id)调用父类,并且唯一对自身的引用将被删除.
现在我可以这样做:
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
当然,在这个例子中,鱼仍指向该生物对象,因此它不是垃圾收集的.但最终,生物会根据规则被创造并互相吃掉,所以我不会单独命名它们.
解决方法
我认为问题在于你认为程序本身就是这些模拟事物生存的世界,而不是模拟它.
fish = Creature.new croc = Crocodile.new $world = [fish,croc] class Crocodile def eat(creature) @energy += creature.energy $world.delete creature end end croc.eat fish world # [croc],now all by his lonesome,the last creature in the world :(
并且假设fish变量已经超出范围,就像在正确结构化的程序中那样,该对象现在很可能是垃圾.