一个Ruby对象能破坏另一个吗?

Nat*_*ong 6 ruby garbage-collection

在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)
Run Code Online (Sandbox Code Playgroud)

在鳄鱼吃掉一个生物并吸收其能量后,该生物应该不再存在.但是上面的代码并没有破坏这个生物.

我知道,如果我说fish = nil,变量fish引用的对象将被垃圾收集.但是creature = nil在Crocodile的eat方法中说不能做到这一点.

另一种方式

从croc.eat里面,我可以说"因为变量'鱼'被传递给我,当我完成后,我要把'鱼'设置为零?"

更新:问题解决了

我基本上采取了Chuck建议的方法,并进行了一些修改.这是我的推理:

  1. 如果不再有任何指向对象的变量,它将被垃圾收集
  2. 如果在创建对象时,我将其添加到散列(如'x'=>对象),并且不为其创建任何其他变量,然后从散列中删除该项导致垃圾收集对象
  3. 似乎合乎逻辑的是,所有生物的列表都应该存储在Creature类中

因此,我这样做了:

  1. 在Creature类对象上,我创建了一个哈希并将其分配给一个实例变量.我们称之为@creaturelist.(我使用实例变量而不是类变量的原因是任何子类都Creature可以拥有自己的列表.)
  2. 在Initialize方法中,一个新生物将自己交给Creature类
  3. Creature类将对该生物的引用添加到该生物并向该生物@creaturelist返回一个ID.
  4. 该生物会在自己的@id变量中记住该ID .
  5. 如果该生物死亡,它会调用父类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
Run Code Online (Sandbox Code Playgroud)

当然,在这个例子中,fish仍然指向该生物对象,因此它不是垃圾收集的.但最终,生物会根据规则被创造并互相吃掉,所以我不会单独命名它们.

Chu*_*uck 7

我认为问题在于你认为程序本身就是这些模拟事物生存的世界,而不是模拟它.

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 :(
Run Code Online (Sandbox Code Playgroud)

并且假设fish变量已经超出范围,就像在正确结构化的程序中一样,该对象现在很可能是垃圾.