Один объект Ruby может уничтожить другого?

В 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, объект, что varible fish относится к, будет собран "мусор". Но высказывание creature = nil в Крокодиле eat метод не выполняет это.

Другой способ поместить его

Из croc.eat я могу сказать, "так как переменная 'рыба' была передана мне, когда я сделан, я собираюсь установить 'рыбу' на ноль?"

Обновление: проблема решена

Я по существу проявил подход что предложенный Chuck с некоторыми модификациями. Здесь было мое обоснование:

  1. Если больше не будет никакой переменной, указывающей на объект, то она будет собрана "мусор"
  2. Если, когда объект создается, я добавляю его к хешу (как 'x' => объект) и не создаю никакую другую переменную для него, то удаление того объекта от хеша приводит к сборке "мусора" объекта
  3. Кажется логичным, что список всех созданий должен быть сохранен в классе Создания

Поэтому я сделал это:

  1. На объекте класса Создания я создал хеш и присвоил его переменной экземпляра. Мы назовем его @creaturelist. (Причина, я использовал переменную экземпляра и не переменную класса, состоит в том так, чтобы любой подкласс Creature может иметь его собственный список, также.)
  2. В Инициализировать методе новое создание вручает себя классу Создания
  3. Класс Создания добавляет ссылку на то создание к @creaturelist и возвращает идентификатор созданию.
  4. Создание помнит что идентификатор в его собственном @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

Конечно, в этом примере, fish неподвижные точки к тому объекту создания, таким образом, это не собрало "мусор". Но в конечном счете, создания будут созданы и съедят друг друга на основе правил, таким образом, я не буду индивидуально называть их.

6
задан Nathan Long 28 December 2009 в 13:35
поделиться

5 ответов

Я думаю, проблема в том, что вы думаете о самой программе как о мире, в котором живут эти смоделированные объекты, а не о том, что они имитируют.

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 :(

И предполагая, что рыба ] вышла за пределы области видимости, как это было бы в правильно структурированной программе, этот объект, скорее всего, теперь будет мусором.

7
ответ дан 10 December 2019 в 00:39
поделиться

Ничто не может быть безопасно обработано сборщиком мусора, пока на него не будет ссылок ни в одной активной области.

2
ответ дан 10 December 2019 в 00:39
поделиться

croc.eat (fish) обнулит ссылку croc на Существо, на которое ссылается рыба, но обратите внимание, что сама переменная «fish» по-прежнему содержит ссылку на это Существо, поэтому экземпляр не является мусором. .

править: Подумайте об этом так: внутри крокодила вы не получаете рыбу, вы получаете копию того, что находится внутри рыбы. Значение fish - это ссылка на объект, созданный с помощью Creature.new. Копия этой ссылки копируется в переменное существо, когда вы выполняете croc.eat (fish). Итак, теперь и рыба, и существо ссылаются на один и тот же объект.

Это похоже на воздушный шар, плавающий в воздухе с привязанными к нему двумя нитями. рыба держит одну веревку, а существо держит другую. когда вы устанавливаете для существа значение nil, оно освобождает воздушный шар,

1
ответ дан 10 December 2019 в 00:39
поделиться

Вы не «уничтожаете объект» - GC делает это за вас. Вы говорите о том, что находитесь в методе и обращаетесь к области действия вызывающего и меняете там привязку.

Если привязка была частью объекта, и вы передали объект, вы могли бы переназначить его (на ноль) оттуда.

0
ответ дан 10 December 2019 в 00:39
поделиться

Один объект Ruby (обычно) не должен уничтожать другой. Это не ваша работа - беспокоиться о том, существуют ли еще объекты или нет. Единственным исключением может быть случай, если вы используете хранилище базы данных - там вы можете заботиться о том, будут ли удалены объекты или нет.

Но в целом мой ответ: вам не нужно об этом заботиться. (Хотя другие ответы имеют смысл.)

0
ответ дан 10 December 2019 в 00:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: