【发布时间】:2009-12-23 22:54:41
【问题描述】:
在 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,变量fish 所指的对象将被垃圾回收。但是在 Crocodile 的 eat 方法中说 creature = nil 并不能做到这一点。
另一种说法
在 croc.eat 中,我可以说“既然变量 'fish' 已传递给我,当我完成后,我要将 'fish' 设置为 nil 吗?”
更新:问题已解决
我基本上采用了 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 仍然指向那个生物对象,所以它不会被垃圾回收。但最终,生物会根据规则被创造出来并互相吃掉,所以我不会单独命名它们。
【问题讨论】:
-
感谢大家帮助我更好地了解可能性。 :)