Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Перечисляемый тип на AS3 (http://www.flasher.ru/forum/showthread.php?t=206336)

Фенёк 28.01.2014 19:48

Перечисляемый тип на AS3
 
Вечер добрый, господа соратники.

Давеча загадали мне загадку: необходимо написать на AS3 перечисляемый тип. Реализовать используя классы Enumeration, IntEnumeration, UintEnumeration, StringEnumeration, которые так же полагается реализовать самостоятельно. Ну и приведены примеры использования

Код AS3:

        public class UnitType extends UintEnumeration
        {
                public static const HERO:UnitType      = new UnitType(1);
                public static const WARRIOR:UnitType = new UnitType(2);
                public static const MAGE:UnitType      = new UnitType(3);
 
                public static const ENEMY:UnitType    = new UnitType(4);
 
 
 
                public function UnitType(val:uint)
                {
                        value = val;
                }
        }

Код AS3:

        public class UnitUpgradeType extends StringEnumeration
        {
                public static const U1:UnitUpgradeType = new UnitUpgradeType("U1");
                public static const U2:UnitUpgradeType = new UnitUpgradeType("U2");
                public static const U3:UnitUpgradeType = new UnitUpgradeType("U3");
                public static const U3:UnitUpgradeType = new UnitUpgradeType("U4");
 
 
 
                public function UnitUpgradeType(val:String)
                {
                        value = val;
                }
        }

Модифицировать приведенные в использовании классы запрещается.

Я прочел некоторое количество статей по реализации этого паттерна, но в условия задачи он не уложился. А не уложился он потому, что при невозможности модифицировать класс, необходимо было реализовать метод etElementsList(enumerationClass:Class):Vector.<Enumeration> который должен был отдавать все значения перечисления.

Насчет задачи вывода значений перечисления меня посетила только одна мысль: ведь любой класс, это на самом деле объект класса Class и по идее должна быть возможность просмотреть его свойства, ведь задавая статические константы мы задаем константы для объекта-класса.

то есть например
Код AS3:

                for (var property:String in SomeClass)
                {
                    trace(property)
                }

но, как вы все уже догадались, эта идея с треском провалилась.

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

Вобщем у меня два вопроса, в связи с моим провалом:

1) Есть ли возможность при таких условиях добраться-таки до всех значений статических констант?
2) Есть ли возможность при таких условиях закрыть классы для создания экземпляров извне?

expl 28.01.2014 20:34

Цитата:

1) Есть ли возможность при таких условиях добраться-таки до всех значений статических констант?
Узнать тип объекта: getQualifiedClassName(this) (http://www.flasher.ru/forum/showthread.php?t=132772;
Получить список полей можно при помощи методов: getDefinitionByName, describeType

Только зачем вам этот список полей? Ведь в приведённом вами коде нет примеров где он нужен,
а чтобы эти примеры компилировались достаточно просто написать:

Код AS3:

public class UintEnumeration
{
    public uint value;
}
 
public class StringEnumeration
{
    public string value;
}

Т.е. чего-то не договариваете вы - примеров использования UnitType нет.
Как тогда понять какой функционал надо запихнуть в UintEnumeration?

Цитата:

2) Есть ли возможность при таких условиях закрыть классы для создания экземпляров извне?
Отличить создание и присвоение статическому полю от всех остальных созданий? Только каким-нибудь злым колдунством.

Akopalipsis 28.01.2014 21:00

Вот только если Вы хотите узнать о статических свойствах класса, то describeType не поможет, он их не видит.

silin 28.01.2014 21:27

describeType нормально видит статические константы
насчет закрыть классы для создания экземпляров извне при таких условиях - действительно непонятно о каких условиях речь, "Модифицировать приведенные в использовании классы запрещается" или что?

СлаваRa 28.01.2014 21:29

@Akopalipsis, вы не правы, describeType работает и показывает статику если в качестве аргумента методу будет передан класс, если же необходимо работать с объектом, то можно сделать так:
Код AS3:

describeType(this["constructor"])

Добавлено через 7 минут
А еще можно вот тут почитать http://www.flasher.ru/forum/blog.php?b=131

Akopalipsis 28.01.2014 22:11

Да, ошибся, я вот как пробовал -
Код AS3:

package 
{
        public class StorageClass
        {
                public static const STATIC_PROP:TestClass = new TestClass();
        }
}

Код AS3:

package 
{
        import flash.display.Sprite;
        import flash.utils.describeType;
 
        public class Main extends Sprite
        {
                public function Main()
                {
                        var storageClass:StorageClass = new StorageClass();
                        trace(describeType(StorageClass));//так видит, а вот если ссылку передать, то нет
                }
 
        }
}


dimarik 28.01.2014 23:38

Код AS3:

public class Enumeration {
    public function Enumeration(id:*) {
        this.id = id;
    }
 
    public var id:*;
 
    public function etElementsList(/*enumerationClass:Class этот параметр, к.м.к., не имеет смысла */):Vector.<Enumeration> {
        return null;
    }
 
    public function toString():String {
        return this.id.toString();
    }
}
 
public class UintEnumeration extends Enumeration {
    public function UintEnumeration(id:uint) {
        super(id);
    }
}
 
public class UnitType extends UintEnumeration {
    public static const HERO:      UnitType = new UnitType(1);
    public static const WARRIOR:  UnitType = new UnitType(2);
    public static const MAGE:      UnitType = new UnitType(3);
    public static const ENEMY:    UnitType = new UnitType(4);
 
    private static const _elementsList:Vector.<Enumeration> = new <Enumeration>[HERO, WARRIOR, MAGE, ENEMY];
 
    public function UnitType(id:uint) {
        super(id);
    }
 
    public override function etElementsList(/*enumerationClass:Class*/):Vector.<Enumeration> {
        return _elementsList.slice();
    }
 
}


Фенёк 29.01.2014 01:17

Ого, оперативно вы )

Насчет describeType большое спасибо, это очень помогло. Я уж было думал, что все это можно сделать если только каким-нибудь безумно грязным хаком, а тут оказывается есть готовая утилитка.

Сегодня-завтра накидаю демку того, что хотелось бы получить в результате, чтобы исключить неоднозначности в вопросах, а то пост писал несколько второпях, уходя с работы. Больше так не буду )

djyamato 29.01.2014 10:06

интересная тема, спасибо всем

Фенёк 29.01.2014 11:50

Итак, поехали.

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

Цитата:

Написать на ActionScript перечисляемый тип и объяснить, почему это хорошо.
Реализуется классами Enumeration, IntEnumeration, UintEnumeration, StringEnumeration.

Использование.

public class UnitType extends UintEnumeration
{
public static const HERO:UnitType = new UnitType(1);
public static const WARRIOR:UnitType = new UnitType(2);
public static const MAGE:UnitType = new UnitType(3);

public static const ENEMY:UnitType = new UnitType(4);



public function UnitType(val:uint)
{
value = val;
}
}

public class UnitUpgradeType extends StringEnumeration
{
public static const U1:UnitUpgradeType = new UnitUpgradeType("U1");
public static const U2:UnitUpgradeType = new UnitUpgradeType("U2");
public static const U3:UnitUpgradeType = new UnitUpgradeType("U3");
public static const U3:UnitUpgradeType = new UnitUpgradeType("U4");



public function UnitUpgradeType(val:String)
{
value = val;
}
}

Ничего больше в классах UnitType и UnitUpgradeType быть не должно (иначе задание теряет смысл).
Все значения перечисляемого типа могут быть объявлены его статическими константами и только ими. Если это не так - проект падает сразу после компиляции или содержит варнинги.
Есть метод function getElementsList(enumerationClass:Class):Vector.<Enumeration> - отдает все значения перечисления.
Есть метод getElementByValue(value:*, enumClass:Class):Enumeration - отдает элемент перечисления по значению.

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

Для чего такая длинная цепочка наследования классов(Enumeration, UintEnumeration, StringEnumeration), я так и не понял, поскольку условиями задачи запрещается даже вызывать конструктор суперкласса в UnitType и UnitUpgradeType. Из-за чего иерархия классов в моем представлении сложлась следующим, весьма нелепым, образом:

класс Enumeration:
Код AS3:

 
    public class Enumeration
    {
        protected var _value:*;
 
        public function Enumeration()
        {
 
        }
 
        public function get value():*
        {
            return _value;
        }
 
    }

класс UintEnumeration:
Код AS3:

    public class UintEnumeration extends Enumeration
    {
 
        public function UintEnumeration()
        {
 
        }
 
    }

Класс StringEnumeration
Код AS3:

    public class StringEnumeration extends Enumeration
    {
 
        public function StringEnumeration()
        {
 
        }
 
    }

То есть по факту, классы наследники мне пришлось оставить пустыми, потому как больше ничего поделать я с ними не могу.

Кстати, попутно еще один вопрос: могу ли я в классах наследниках переписать так метод get value() чтобы он возвращал значения другого типа? Так как в данной ситуации, это могла быть единственная польза принесенная таким наследованием.

Далее. Я так понял что методы getElementsList(enumerationClass:Class):Vector.<Enumeration> и getElementByValue(value:*, enumClass:Class):Enumeration это методы, напрмер, объекта Main. В этом случае передаваемй параметр все таки имеет существенное значение.


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

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