Как вы позволяете 2 объектам, принадлежащим родительскому объекту, общаться друг с другом в Ruby? - PullRequest
0 голосов
/ 01 июня 2011

Прежде всего, извините, если это вопрос n00b.Я веб-разработчик-самоучка, и это мой первый настоящий опыт в приложениях.Я пытался найти ответ на то, что я ищу, но я не уверен в правильной терминологии и поэтому не нашел соответствующих результатов.Я полагаю, это потому, что либо я не знаю, как правильно спрашивать, что мне нужно;ответ настолько очевиден, что не нужно писать о нем, или то, что я спрашиваю, настолько глупо, что понятия не существует, и я должен полностью сделать это по-другому.

В любом случае, на мой вопрос.Я работаю над приложением, в котором есть 3 класса, которые доставляют мне неприятности.Существует MainContainer, который в основном обрабатывает пользовательский интерфейс;«Назначитель», который выбирает задачи для выполнения;и «работник», который выполняет задачи.Это на очень ранней стадии, но сейчас это выглядит примерно так.

class MainContainer

  def setup
    @worker = Worker.new(:x => 200, :y => 200)
    @assigner = Assigner.new(:x => 400, :y => 300)
  end

  # update & draw code
end

class Assigner

  def set_target
    parent.worker.target self.x, self.y
  end

  # input, update & draw code
end

class Worker < GameObject

  def target(tx, ty)
    @target_x = tx
    @target_y = ty
    @has_task = true
  end

  # update & draw code
end

Основной поток приложения выглядит примерно так: загружается экземпляр MainContainer, который отображает на экране пользовательский интерфейс, включая исполнителя и работника.Затем пользователь использует присваиватель для перемещения по пользовательскому интерфейсу и выбора задачи.До этого момента все работает отлично.

Что я не могу понять, так это то, как Назначитель может передать значение работнику.Код, который я имею в этом примере, является методом set_target работника.Строка parent.worker.target self.x, self.y - самая последняя из моих попыток.Другие вещи, которые я здесь пробовал, включают такие вещи, как @worker.target self.x, self.y

Я думал о том, чтобы передать @worker в @assigner, но план состоит в том, чтобы было произвольное число работников, которое увеличится/ уменьшается со временем.Я планирую обработать их с помощью WorkerManager, который будет отслеживать, сколько рабочих в настоящее время доступно, но если я передам это в @assigner, не будет ли это просто переданной копией?Я все еще далека от реализации чего-то подобного, поэтому я не проверял это, может быть, это путь?

Еще одна вещь, о которой я подумал, это иметь работника в качестве глобального, но этоэто проблема, которая, скорее всего, будет возникать снова довольно часто, поэтому я в конечном итоге получу приложение, полное глобальных переменных, я думаю, что это не правильный путь!

Я из web-разработчика, поэтому единственный другойРешение, которое я могу придумать, заключается в том, чтобы создать базу данных.Это последнее средство, если я не смогу сделать что-нибудь еще.

В любом случае, переформулировать мой вопрос.В экземпляре MainContainer, как я могу заставить его Assigner и Worker передавать данные между собой?

Я бы очень признателен за любую помощь, даже если она выглядит примерно так: "stfu n00b, прочитайте это: -relevant link".

Ответы [ 2 ]

1 голос
/ 01 июня 2011

На мой ответ может повлиять тот факт, что я не совсем понял суть вопроса, поэтому, пожалуйста, помните об этом и исправьте меня, если я ошибаюсь.

Вероятно, лучшим способом было бы полностью изолировать работника и присваивателя и поместить всю логику в контроллер.

Однако, если вам нужно больше общения между работниками и вы хотите, чтобы в него были вовлечены цеденты, то для цедента может быть хорошей идеей знать о работниках, которых он создал, и работникам, чтобы знать, какой цедент их создал. Затем назначители должны отвечать за создание рабочих (и контроллер за создание назначителей). Что-то вроде (некрасивый, неоптимизированный и не проверенный код):

class Assigner
  attr_reader :workers
  def initialize
    @workers = []
  end
  def create_worker
    worker = Worker.new
    worker.assigner = self
    @workers << worker
    worker
  end
end

class Worker
  attr_accessor :assigner
end

Конечно, вам необходимо управлять сбором работников для каждого цессионария и, например, удалите неактивных работников, как только они закончат свою работу.

Все в Ruby передается как ссылка, поэтому копирование объектов в вызовах методов не требуется. обсуждение на форуме ruby ​​можно найти . (Это вы также задавались вопросом в вашем вопросе.)

Надеюсь, мой ответ поможет. Если нет, укажите это в комментарии, и я постараюсь улучшить его.

1 голос
/ 01 июня 2011

Я думаю, что где-то есть недостаток в дизайне. Вы говорите, что Assigner выбирает задачу, а Worker выполняет ее. Не похоже, что им нужно общаться. Если им нужно, они могут делать больше, чем вы описали, что может указывать на возможность рефакторинга в более изолированные классы с меньшим количеством обязанностей.

Итак, что, если MainContainer имеет полный контроль?

def main
  @worker = Worker.new
  @assigner = Assigner.new
  target = @assigner.target
  result = @worker.do_work(target)
  update_ui(result)
end

Пользовательский интерфейс действительно должен быть отделен от бизнес-логики, приведенный выше псевдокод просто иллюстрирует идею предоставления контроля MainContainer, чтобы избежать того, чтобы Worker и Assigner могли общаться друг с другом. Это также позволит вам обрабатывать несколько рабочих в случае необходимости.

Надеюсь, это поможет.

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