это неправильный способ наследования? - PullRequest
0 голосов
/ 10 февраля 2012

Я не знаю, выбрал ли я хорошее название или нет, но я разрабатываю простую карточную игру, и это мой сценарий:

У меня есть класс с именем Player , и я создал несколько объектов (скажем, 4) из Player. В каждом раунде игры у нас есть особый вид игрока, скажем SpecialPlayer , что в каждом раунде один из этих 4 игроков может быть SpecialPlayer.

SpecialPlayer - простой игрок, плюс он может делать еще кое-что, скажем, приостановить / перезапустить игру. Поэтому я унаследовал от Player и создал SpecialPlayer и добавил 2 метода в этот класс. Проблема в том, что когда я создаю экземпляр SpecialPlayer, у меня будет еще один объект плюс эти 4 объекта игрока, это нормально, но я хочу иметь возможность изменять свойства в SpecialPlayer и видеть эффекты для объекта Player, который был SpecialPlayer в этом раунде

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

Является ли наследование здесь неправильным? мне нужно составить класс Player в классе SpecialPlayer?

Если это может изменить ответ, я должен сказать, что я использую Ruby .

Ответы [ 4 ]

2 голосов
/ 10 февраля 2012

Поскольку объект SpecialPlayer должен заменять объект Player в конце каждого раунда, я думаю, что было бы более уместным НЕ создавать класс SpecialPlayer для расширения Player.

Вместо этого я добавил бы в проигрыватель флаг, чтобы пометить его как особый (булево специальное), и в соответствии с этим я бы знал, может ли он выполнять специальные функции.

1 голос
/ 11 февраля 2012

Мне придётся не соглашаться с другими и сказать вам, что это звучит так, как будто вам нужно расширить ваш Player экземпляр с помощью модуля SpecialPlayer.Позвольте мне продемонстрировать.Допустим, у вас есть класс игрока:

class Player
  attr_accessor :game

  def special?
    false
  end
end

Все игроки будут иметь эти методы.Давайте создадим нового игрока:

player = Player.new
player.game = Game.new
player.special? # false

Теперь предположим, что у вас есть SpecialPlayer модуль:

module SpecialPlayer
  def special?
    true
  end

  def pause_game
    game.pause
  end

  def restart_game
    game.restart
  end
end

Ваш модуль еще не изменяет поведение Player, потому что у вас нетсделал что-нибудь для вашего игрока.Итак, давайте расширим наш экземпляр игрока с помощью SpecialPlayer:

player.extend SpecialPlayer
player.special? # true
player.pause_game # pauses the game
player.restart_game # restarts the game

Прелесть этого в том, что любым другим игрокам в системе не нужно заботиться о том, кто особенный или как они это сделали:

other_player = Player.new
other_player.special? # false
other_player.pause_game # NoMethodError: undefined method `pause_game' for #<Player>
other_player.restart_game # NoMethodError: undefined method `restart_game' for #<Player>

Это также гарантирует, что не любой игрок может быть особенным.Вызов #restart_game от не специального игрока даже не сработает, поэтому у вас не будет ошибок, когда обычные игроки делают то, что не должны.

1 голос
/ 11 февраля 2012

Это звучит как работа для шаблона Decorator.Вы можете создать класс SpecialPlayer с тем же интерфейсом (IPlayer), что и обычный класс Player.Класс SpecialPlayer также будет иметь атрибут player (указатель на Player, который является особенным) и метод assignPlayer, который вызывается в конце каждого раунда для установки атрибута player для указателя на нового специального игрока.Все методы класса SpecialPlayer, которые наследуются от IPlayer, должны вызывать соответствующий метод из атрибута player.

0 голосов
/ 11 февраля 2012

Как правило, вы хотите, чтобы поведение Player варьировалось в зависимости от того, является оно особенным или нет. В этом типе проблем полезно инкапсулировать изменяющееся поведение в интерфейсе (IHandling) и позволить исходному классу зависеть от реализации этого интерфейса. В вашем случае вы бы позволили Player делегировать изменяющееся поведение либо SpecialHandling, либо NormalHandling. Ваша обычная обработка ничего не могла сделать. После каждого раунда объект SpecialHandling можно прикрепить к другому Player.

Точки должны храниться в классе Player, так как это обычная функция. Однако предположим, что для умножения баллов на Player нужно было использовать SpecialHandling, класс Player делегировал бы это экземпляру IHandling.

...