Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Вопрос про наследование и State (http://www.flasher.ru/forum/showthread.php?t=215674)

Appleman 22.11.2018 15:31

Вопрос про наследование и State
 
Друзья!

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

Также у Character некоторые методы работают по-разному в зависимости от того, находится он в "обычном" или "боевом" режиме. Реализовано через паттерн проектирования "Состояние" (State). В частности, создан класс ChState и его наследники ChStateNormal и ChStateBattle. Экземпляр текущего состояния получает в конструктор ссылку на персонажа-владельца и записывается у него в переменную _state, через которую вызываются все различающиеся методы. Всё как в книжке.

Теперь вопрос. Что мне делать, если вызываемая версия метода зависит одновременно и от наследника Character (игрок/NPC), и от текущего состояния (Normal/Battle)?

Rzer 23.11.2018 15:58

Ты всегда можешь в коде проверить, какое именно состояние или персонаж у тебя используются, например:

Код AS3:

override function doSomething():void{
  if (_state is ChStateNormal) doSomethingNormal();
  else doSomethingBattle();
}


СлаваRa 23.11.2018 16:02

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

Rzer 23.11.2018 16:19

Всё равно тебе придётся узнать в каком режиме находится стейт.

Можно сделать и так:

Код AS3:

class State{
 
  public static const NORMAL:String = "normal";
  public static const BATTLE:String = "battle";
 
  function getStateType():String {
    return NORMAL;
  }
}

И переопределять этот метод в детях:

Код AS3:

class BattleState{
  override function getStateType():String {
    return State.BATTLE;
  }
}

И проверять в коде:
Код AS3:

override function doSomething():void{
  if (_state.getStateType() == State.NORMAL) doSomethingNormal();
  else doSomethingBattle();
}

Но я не вижу принципиально разницы, если все твои последующие стейты ты будешь наследовать от ChStateNormal или ChStateBattle

Appleman 24.11.2018 14:38

Цитата:

Сообщение от Rzer (Сообщение 1206126)
Всё равно тебе придётся узнать в каком режиме находится стейт.

Вовсе нет. Как отметил СлаваRa, суть самого паттерна "Состояние" в том и состоит, что проверять ничего не нужно. Ты просто записываешь в переменную _state того или иного наследника базового класса (или интерфейса) состояния и переопределяешь в нём методы. Получается, что вместо doSomething(), ты запускаешь _state.doSometing(). По факту запустится метод из актуального на данный момент состояния.

Цитата:

Но я не вижу принципиально разницы, если все твои последующие стейты ты будешь наследовать от ChStateNormal или ChStateBattle
Пока ничего не придумал лучше, чем создать 4 варианта наследников: ChStateBattlePlayer, chStateBattleNPC и аналогично для "обычного" состояния.

Rzer 24.11.2018 18:04

Главное не заработай себе болезнь паттернов. То что ты делаешь сейчас скорее всего большее зло чем просто добавить проверку.

caseyryan 24.11.2018 19:15

Цитата:

Теперь вопрос. Что мне делать, если вызываемая версия метода зависит одновременно и от наследника Character (игрок/NPC), и от текущего состояния (Normal/Battle)?
Так а в чем проблема-то?
У состояния есть ссылка на персонажа. Состояние знает, что у персонажа есть какой-то метод.
Этот метод вызывается. Профит. Состояние Battle вызывает метод hit(), состояние нормал вызывает метод fuckAbout(). Какая состоянию разница что делается внутри этого метода?
Мне кажется, что иногда ты создаешь тему сразу же, как что-то не понял. Даже не успев подумать а есть ли вообще проблема

Appleman 25.11.2018 00:23

caseyryan, на счёт последнего ты не прав. Напротив, с понедельника крутил в голове. Здесь скорее зашоренность: прочитал в книжке, как методы реализуются ВНУТРИ классов-состояний и ни шагу в сторону. Спасибо за совет!

Скажи ещё, как по-твоему, если состояния действительно имеют ссылку на своего владельца, как вообще лучше делать: реализовывать что-то в состояниях, или использовать их как классы-"стрелочники", которые дёргают нужные методы владельцев, а сами ничего не делают?

caseyryan 28.11.2018 12:51

Цитата:

Скажи ещё, как по-твоему, если состояния действительно имеют ссылку на своего владельца, как вообще лучше делать: реализовывать что-то в состояниях, или использовать их как классы-"стрелочники", которые дёргают нужные методы владельцев, а сами ничего не делают?
По-моему, если задача состояния только в том, чтобы определить какой метод дернуть, то оно в принципе не нужно. Достаточно сделать несколько констант, обозначающих состояние и простым свитчем выбирать какой метод дернуть.
В то же время, если состояние для каждого вида врагов будет содержать какую-то вшитую логику, то это тоже гибкости не придает.
Поэтому, я бы на твоем месте остановился на варианте с константами.
Но это мое имхо, решать как делать всё равно тебе

Appleman 05.12.2018 10:12

caseyryan, я наоборот с этого начал и потом ушёл, т.к. слишком раскидистой начала становиться реализация подобной логики. Состояние по факту оказалось достаточно комплексной штукой, влияющей на многие вещи. Это в данном конкретном случае потребовалось дёргать методы.


Часовой пояс GMT +4, время: 21:28.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.