Всякие разные штуки сомнительной полезности сделанные в свободное от работы время.
Enum или Multiton в AS3.
К сожалению в AS3 enum на уровне языка не реализован, но если очень хочется, то, конечно, можно
Понятное дело, что будь он реализован на уровне языка - он был бы более эффективным и удобным, но, тем не менее, даже в такой версии у него есть некоторые преимущества перед обычными строковыми или чисельными константами.
Итак, про преимущества:
Зачастую я сталкиваюсь с ситуацией, когда метод или свойство должны принимать значения простых типов, но набор значений должен быть ограничен. Одно из возможных решений в таком случае - проверить ввод сопоставлением с набором заготовленых констант и в случае несоответствия высказать свое неодобрение в виде ошибки. Недостаток такого подхода заключается в том, что строки и числа сравниваются по значению, в то время как объекты сравниваются по ссылке. Второе, не значительно, но быстрее. Кроме того, писать в каждом сеттере которому нужно принимать только определенные значения switch-case или if-else проверяющий валидность инпута - ну, согласитесь, не комильфо
Используя Enum мы решаем проблему валидации такого ввода раз и на всегда. К сожалению, компилятор нас не остановит если мы попытаемся создать "не кондиционный" enum - но с этим уже ничего не поделаешь... зато в любом месте, где бы я раньше должен был делать валидацию строк или чисел, я теперь спокойно могу от нее избавиться.
Вот небольшой пример. Я думаю, что код в дополнительных комментариях не нуждается:
package examples { /** * AuthEnum class. * @author wvxvw * @langVersion 3.0 * @playerVersion 10.0.32 */ public class AuthEnum { //-------------------------------------------------------------------------- // // Public properties // //-------------------------------------------------------------------------- /** * Used to set the <code>state</code>. * @see AuthModel#state */ public static const AGREEMENT:AuthEnum = new AuthEnum("agreement"); /** * Used to set the <code>state</code>. * @see AuthModel#state */ public static const CONFIRM:AuthEnum = new AuthEnum("confirm"); /** * Used to set the <code>state</code>. * @see AuthModel#state */ public static const LOGIN:AuthEnum = new AuthEnum("login"); /** * Used to set the <code>state</code>. * @see AuthModel#state */ public static const MANAGE:AuthEnum = new AuthEnum("manage"); /** * Used to set the <code>state</code>. * @see AuthModel#state */ public static const SURVEY:AuthEnum = new AuthEnum("survey"); /** * Used to set the <code>state</code>. * @see AuthModel#state */ public static const UPLOAD:AuthEnum = new AuthEnum("upload"); //-------------------------------------------------------------------------- // // Private properties // //-------------------------------------------------------------------------- private var _num:String; private static var _lockUp:Boolean; //-------------------------------------------------------------------------- // // Cunstructor // //-------------------------------------------------------------------------- /** * All instance of this enum are created at the application initialization time. * Users should not create additional instances. * * @param num The string key to represent this instance. */ public function AuthEnum(num:String) { super(); if (_lockUp) throw new Error("This application domain already initialized this enum."); _num = num; } //-------------------------------------------------------------------------- // // Public methods // //-------------------------------------------------------------------------- public static function lockUp():void { _lockUp = true; } /** * Decorates this enumerator with the name assigned to it. * * @return the name assigned to this enumerator. */ public function toString():String { return this._num; } /** * We may need to compare enums to their string represenation using non-strict equality. * This will allow non-strict comparison to succeed. * * @return the string value wrapped by this enum instance. */ public function valueOf():Object { return this._num; } } } import examples.AuthEnum; AuthEnum.lockUp();
package examples { //{ imports import flash.display.Sprite; //} public class TestAuthEnum extends Sprite { //-------------------------------------------------------------------------- // // Cunstructor // //-------------------------------------------------------------------------- public function TestAuthEnum() { super(); this.testEnum(AuthEnum.LOGIN); try { new AuthEnum("foo"); } catch (error:Error) { trace(error); } } //-------------------------------------------------------------------------- // // Public methods // //-------------------------------------------------------------------------- public function testEnum(para:AuthEnum):void { switch (para) { case AuthEnum.AGREEMENT: trace("case AuthEnum.AGREEMENT", para); break; case AuthEnum.CONFIRM: trace("case AuthEnum.CONFIRM", para); break; case AuthEnum.LOGIN: trace("case AuthEnum.LOGIN", para); break; case AuthEnum.MANAGE: trace("case AuthEnum.MANAGE", para); break; case AuthEnum.SURVEY: trace("case AuthEnum.SURVEY", para); break; case AuthEnum.UPLOAD: trace("case AuthEnum.UPLOAD", para); break; } } } }
Всего комментариев 11
Комментарии
18.12.2009 03:51 | |
То же самое http://100mbit.ru/?p=76
Минус: Нельзя использовать данный тип в качестве дефолтного значения при указывании параметров. |
18.12.2009 14:01 | |
Упс... я чесно эту статью не читал Ну вот, изобрел велосипед... хотя у меня по крайней мере есть решение против создания некондиционных инстансов энумератора. А с дефолтными параметрами - конечно облом... но ничего не поделаешь... на самом деле есть еще облом - о нем неявно сказано в сообщении об ошибке - энум создается не на этапе компиляции, а во время инициализации (загрузки) флешки - а это значит что в разных домейнах, ну или если сильно извратится то и просто в том же домейне можно ему "навредить"... Кроме того, по сравнению с нормальной имплементацией энумератора эта наверняка избыточна т.как энуму не нужны свойства и методы, например. Но это уже издержки производства - лучше все равно не будет.
EDIT: Да, и это - тип то можно использовать с дефолтными параметрами - т.как null его спокойно заменить, а вот инстанс - конечно не получится. EDIT2: Да, вот еще: если кому пригодится - сделал темплейт для FD: Код:
package $(Package) $(CSLB){ //{ imports import org.wvxvws.utils.EnumError; //} /** $(CBI)* $(FileName) class. $(CBI)* @author $(DefaultUser) $(CBI)* @langVersion $(langVersion) $(CBI)* @playerVersion $(playerVersion) $(CBI)*/ public class $(FileName) $(CSLB){ //-------------------------------------------------------------------------- // // Public properties // //-------------------------------------------------------------------------- public static const FOO:$(FileName) = new $(FileName)("foo"); //-------------------------------------------------------------------------- // // Private properties // //-------------------------------------------------------------------------- private var _num:String; private static var _lockUp:Boolean; //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** $(CBI)* All instance of this enum are created at the application initialization time. $(CBI)* Users should not create additional instances. $(CBI)* $(CBI)* @param num The string key to represent this instance. $(CBI)*/ public function $(FileName)(num:String)$(CSLB){ super(); if (_lockUp) throw new EnumError(); _num = num; } //-------------------------------------------------------------------------- // // Public methods // //-------------------------------------------------------------------------- public static function lockUp():void { _lockUp = true; } /** $(CBI)* Decorates this enumerator with the name assigned to it. $(CBI)* $(CBI)* @return the name assigned to this enumerator. $(CBI)*/ public function toString():String { return this._num; } /** $(CBI)* We may need to compare enums to their string represenation using non-strict equality. $(CBI)* This will allow non-strict comparison to succeed. $(CBI)* $(CBI)* @return the string value wrapped by this enum instance. $(CBI)*/ public function valueOf():Object { return this._num; } } } import $(Package).$(FileName); $(FileName).lockUp(); |
|
Обновил(-а) wvxvw 18.12.2009 в 15:18
|
24.12.2009 13:55 | |
Класс. И я как раз задумывался как enum реализовать в AS3.0. А тут решение, да не одно. Спасибо.
Add: еще бы туториал как темплйт создать для FD, или сразу бы в *.fdt формате. |
|
Обновил(-а) Волгоградец 24.12.2009 в 14:02
|
25.12.2009 16:17 | |
27.07.2010 13:00 | |
То есть это по сути возможность использовать проверку на тип энемератора с одновременной блокировкой от создания фиктивного нового значения для передачи вместо существующих энумов.
|
27.07.2010 13:24 | |
Будем надеятся, что появится родной Enum
|
27.07.2010 15:31 | |
SunShadow: так и есть.
terbooter: тут прямо как в пословице, три года ждать - это в лучшем случае |
Последние записи от wvxvw
- Dired - текстовый проводник по файловой системе (29.06.2013)
- Навигация по HTML с WASD (09.06.2012)
- JavaScript, все не так плохо (07.06.2012)
- Что такое tarball и чем его пакуют (11.04.2012)
- Критика Presentation Model (18.02.2012)