Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Проверить на наличие геттера (http://www.flasher.ru/forum/showthread.php?t=215632)

caseyryan 28.07.2018 17:31

Цитата:

Ужас - в самом подходе или в его реализации? Не стесняйся, мне самому не нравится, но ничего лучше не придумалось пока.
Не совсем понимаю что ты хочешь сделать, но если у тебя эти классы унаследорваны от разных базовых классов, но свойства должно присутствовать обязательно, то почему ты не используешь интерфейсы?

Appleman 29.07.2018 23:05

СлаваRa, caseyryan, согласен, подход - дерьмо.

Цитата:

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

Давайте я попробую привести ещё пример и задать вопрос.

Изначально в классе Character были прописаны свойства из "досье", которые остаются неизменными (сила, интеллект), свойства, отслеживающих текущие параметры (энергия, ХП), скиллы. От такой огромной простыни (сами свойства, сеттеры/геттеры, методы обработки) у меня класс сильно "распух". Чтобы всё это хозяйство организовать, придумалось раскидать свойства не нескольким новым классам. Но возникла новая проблема. У меня происходит много обращений за значениями свойств, переданных как параметры. Наиболее типичный случай - класс проверки условий доступности игровых действий. Вот его пример:

Код AS3:

public class ACPropEquality extends ACEntity 
        {
                private var _value: * ;
 
                public function ACPropEquality(newOwnerID: String, newPropID: String, newValue: *)
                {
                        super(newOwnerID, newPropID);
                        _value = newValue;
                }
 
                override public function testCondition(action:ActionEntity) : Boolean
                {
                        super.getOwner(action);
                        return (_owner.getProp(_propID) == _value);
                }
        }

Получается, что под newPropID может быть свойство из досье, текущий параметр или скилл. Я рассуждал так, что другие классы не должны "знать" и "вникать", где конкретно в классе персонажа "живёт" запрашиваемый параметр, а просто передать ID свойства и получить назад текущее значение. В этом случае встаёт вопрос, как в самом Character идентифицировать, где искать свойство под полученным ID. Результат - как видели выше.

Или я вас не правильно понял, и главный объект критики - это подход, при котором запросы текущих значений свойств сделаны через их строковые идентификаторы?

СлаваRa 29.07.2018 23:56

Цитата:

Или я вас не правильно понял, и главный объект критики - это подход, при котором запросы текущих значений свойств сделаны через их строковые идентификаторы?
бинго!

Appleman 30.07.2018 15:52

Отлично! Друзья, я вам буду очень признателен за любую наводку на более "красивое" решение.

Я попытался максимально компактно и доходчиво сформулировать ниже, почему у меня активно применяются строковые ID.

Класс игрового действия состоит из 3-х компонентов: справочных данных (ActionData), а также 2-х персонажей, один из которых - "актор" (кто активно действует), а второй - "реципиент" (кто принимает эффект от действия). Вот смотрите кусочек класса ActionEntity:

Код AS3:

protected var _actionData: ADEntity;         // Данные выполняемого действия
protected var _actor: Character;                // Актор - активный участник, совершающий действие
protected var _recipient: Character;        // Реципиент - пассивный участник, получающий эффект от действия
 
public function ActionEntity(data: ADEntity, character1: Character, character2: Character = null)
                {
                        _actionData = data;
                        this.recognizeRoles(character1, character2);
                }

Обратите внимание, что если, например, действие рассчитано на одного персонажа (например, применить на себя какой-нибудь предмет), то в таком случае в конструктор будет передан один персонаж, который будет и актором, и реципиентом. С этим разбирается метод recognizeRoles(). Он запускается прямо в конструкторе и сохраняет полученных персонажей в абстрактных переменных _actor и _recipient.

ActionData (наследник класса ADEntity) - содержит "справочные" данные действия. Они неизменны, и теоретически их можно (и наверное нужно) вообще из кода перенести куда-нибудь, но сейчас не об этом. Важно, что там формулируются условия нескольких видов: критические (при их невыполнении действие не будет создано), видимости (действие не будет выведено игроку) и активности (действие будет неактивно). Вот как это сделано сейчас:

Код AS3:

public class ADEntity
{
        protected var _criticalConditions: Vector.<ACEntity> = new Vector.<ACEntity>;
        protected var _visibleConditions: Vector.<ACEntity> = new Vector.<ACEntity>;
        protected var _activeConditions: Vector.<ACEntity> = new Vector.<ACEntity>;
}

В каждом векторе - набор одновременно выполняемых условий - наследники класса ACEntity. В своём предыдущем сообщении я приводил код одного из его наследников - класса ACPropEquality, проверяющего свойство на равенство указанному значению.

Вот маленький кусочек кода, где создаётся действие рукопашной атаки:

Код AS3:

_act = new ADDoubleMelee(ActionIDs.MELEE); 
_act.criticalConditions = new <ACEntity>
        [
        new ACPropEquality(ActionIDs.OWNER_ACTOR, ChIDs.RPG_CLASS, ChIDs.CLASS_FIGHTER)
        ];

Загвоздка в том, что, будучи прописанными в классе ADEntity, условия "не знают" и "не могут знать", что за действующие лица попадут в конструктор ActionEntity. Как мне сформулировать необходимость проверки каких-то свойств экземпляров Character в классе, не имеющим на них ссылок. Вот я и выкрутился со строковыми идентификаторами.

В классе ActionEntity запуск проверки условий выглядит так:
Код AS3:

public function testVisibleConditions() : Boolean
{
        for each (var cond: ACEntity in this._actionData.visibleConditions)
        {
                if (!cond.testCondition(this)) return false;
        }
        return true;
}

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

Добавлено через 21 час 11 минут
Посидел-подумал... Вот такой вариант проверки условий придумался без использования строковых идентификаторов.

Код AS3:

public class ConditionStrength 
        {
                private var _measureMin: Number;
                private var _measureMax: Number;
 
                public function ConditionStrength(measureMin: Number = 0, measureMax: Number = 0)
                {
                        _measureMin = measureMin;
                        _measureMax = measureMax;
                }
 
                public function testCondition(ch: Character) : Boolean
                {
                        if (ch.strength >= _measureMin && ch.strength < _measureMax) return true;
                        return false;
                }
 
        }

Что скажете?

Wormhole 04.08.2018 21:32

Не читал последнее сообщение, но
обращайся напрямую через компоненты, например: character.progression.xp

Либо создай псевдо-свойства в базовом классе с геттерами, которые будут вызывать геттеры соответствующего свойства в его компоненте

Добавлено через 3 минуты
Но на компоненты имеет смысл делить, когда есть еще и дополнительная функциональность, связанная с этими свойствами, иначе получаем запах "Data Object".
Если ее нет, но свойств слишком много, проверь принцип одной обязанности - класс должен отвечать только за что-то одно.
Например, раньше у меня класс игрока содержал две абсолютно несвязанные друг с другом части - представление прогресса игрока и его раскачки и представление игрока в бою (с хп, маной и т. д.). Потом я их разделил на два класса

GBee 06.08.2018 11:53

Вроде интерфейсы прям-таки и напрашиваются.


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

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