Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > e4xu

Всякие разные штуки сомнительной полезности сделанные в свободное от работы время.
Рейтинг: 5.00. Голосов: 4.

Enum или Multiton в AS3.

Запись от wvxvw размещена 17.12.2009 в 03:48
Обновил(-а) wvxvw 27.07.2010 в 13:15

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

Итак, про преимущества:
Зачастую я сталкиваюсь с ситуацией, когда метод или свойство должны принимать значения простых типов, но набор значений должен быть ограничен. Одно из возможных решений в таком случае - проверить ввод сопоставлением с набором заготовленых констант и в случае несоответствия высказать свое неодобрение в виде ошибки. Недостаток такого подхода заключается в том, что строки и числа сравниваются по значению, в то время как объекты сравниваются по ссылке. Второе, не значительно, но быстрее. Кроме того, писать в каждом сеттере которому нужно принимать только определенные значения switch-case или if-else проверяющий валидность инпута - ну, согласитесь, не комильфо
Используя Enum мы решаем проблему валидации такого ввода раз и на всегда. К сожалению, компилятор нас не остановит если мы попытаемся создать "не кондиционный" enum - но с этим уже ничего не поделаешь... зато в любом месте, где бы я раньше должен был делать валидацию строк или чисел, я теперь спокойно могу от нее избавиться.

Вот небольшой пример. Я думаю, что код в дополнительных комментариях не нуждается:

Код AS3:
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();
Тест:
Код AS3:
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 iNils вне форума
iNils
 
Аватар для iNils
То же самое http://100mbit.ru/?p=76
Минус: Нельзя использовать данный тип в качестве дефолтного значения при указывании параметров.
Старый 18.12.2009 14:01 wvxvw вне форума
wvxvw
 
Аватар для wvxvw
Упс... я чесно эту статью не читал Ну вот, изобрел велосипед... хотя у меня по крайней мере есть решение против создания некондиционных инстансов энумератора. А с дефолтными параметрами - конечно облом... но ничего не поделаешь... на самом деле есть еще облом - о нем неявно сказано в сообщении об ошибке - энум создается не на этапе компиляции, а во время инициализации (загрузки) флешки - а это значит что в разных домейнах, ну или если сильно извратится то и просто в том же домейне можно ему "навредить"... Кроме того, по сравнению с нормальной имплементацией энумератора эта наверняка избыточна т.как энуму не нужны свойства и методы, например. Но это уже издержки производства - лучше все равно не будет.

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
Старый 24.12.2009 23:15 wvxvw вне форума
wvxvw
 
Аватар для wvxvw
Ну, не знаю, на туториал это не потянет:
В FD: Tools > Application Files > перейти в папку Templates\ProjectFiles\AS3Project > добавить текстовый файл с расширением *.fdt и скопировать туда содержание темплейта > Перезапустить FD
Старый 25.12.2009 16:17 Волгоградец вне форума
Волгоградец
 
Аватар для Волгоградец
Упс. Все просто. Не в ту папку сначала положил.
И FD ругнулся на
Код AS3:
import org.wvxvws.utils.EnumError;
Старый 27.07.2010 12:34 SunShadow вне форума
SunShadow
 
Аватар для SunShadow
Объясните суть вот этих строк.
Код AS3:
import examples.AuthEnum;
AuthEnum.lockUp();
В каком случае могут быть попытки переопределить константы? Я так понимаю после того как первый раз в приложение будет добавлен нужный enum автоматически будут созданы константы с объектами и они должны оставаться неизменными. Каким же образом их можно попытаться переопределить?
Старый 27.07.2010 12:50 wvxvw вне форума
wvxvw
 
Аватар для wvxvw
Константы переопределить уже никак не получистся, а вот создать новые незапланированые инстансы энумератора - тоже, вобщем-то не хорошо. Вообще, в теории, энумератор нужен для того, чтобы не обрабатывать ошибки в ситуациях когда можно выбрать из множества. Т.е. Boolean - часный случай, представьте, что вам бы каждый раз приходилось бы делать:
Код AS3:
function foo(condition:Boolean):void
{
    if (condition) doSomething();
    else doSomethingElse();
    suddenly throw new ArgumentError();
}
Но, к сожалению, до конца такой функционал не получится сэмулировать в AS3 т.как мы не можем описать тип как необнуляемый Но так мы хотя бы сократим количество непредвиденых вариантов до 1.
Старый 27.07.2010 13:00 SunShadow вне форума
SunShadow
 
Аватар для SunShadow
То есть это по сути возможность использовать проверку на тип энемератора с одновременной блокировкой от создания фиктивного нового значения для передачи вместо существующих энумов.
Старый 27.07.2010 13:24 terbooter вне форума
terbooter
Будем надеятся, что появится родной Enum
Старый 27.07.2010 15:31 wvxvw вне форума
wvxvw
 
Аватар для wvxvw
SunShadow: так и есть.
terbooter: тут прямо как в пословице, три года ждать - это в лучшем случае
Старый 27.07.2010 15:58 SunShadow вне форума
SunShadow
 
Аватар для SunShadow
Маловероятно). Наличие энумов в приложении означает наличие инструмента для создания, редактирования и наконец хранения энумов. А каким образом можно для онлайн приложения сделать общий набор энумов? Я так понимаю кроме способа что предложил уважаемый ничего более-менее стоящего не придумаешь.
Иначе я у себя создам свой набор энумов, вы свой а наши приложения друг друга все равно не поймут.
 

 


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


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