Показать сообщение отдельно
Старый 15.08.2012, 11:58
fljot вне форума Посмотреть профиль Отправить личное сообщение для fljot Найти все сообщения от fljot
  № 1  
Ответить с цитированием
fljot

блогер
Регистрация: Jul 2007
Сообщений: 940
Записей в блоге: 3
По умолчанию Гонки при создании "классовых" ENUM'ов

Есть такой класс GestureState, по сути — ENUM:
Код AS3:
public class GestureState
{
	public static const IDLE:GestureState = new GestureState(1 << 0, "IDLE");
	public static const POSSIBLE:GestureState = new GestureState(1 << 1, "POSSIBLE");
	public static const RECOGNIZED:GestureState = new GestureState(1 << 2, "RECOGNIZED");
	public static const BEGAN:GestureState = new GestureState(1 << 3, "BEGAN");
	public static const CHANGED:GestureState = new GestureState(1 << 4, "CHANGED");
	public static const ENDED:GestureState = new GestureState(1 << 5, "ENDED");
	public static const CANCELLED:GestureState = new GestureState(1 << 6, "CANCELLED");
	public static const FAILED:GestureState = new GestureState(1 << 7, "FAILED");
 
	private static const endStatesBitMask:uint =
		GestureState.CANCELLED.toUint() |
		GestureState.RECOGNIZED.toUint() |
		GestureState.ENDED.toUint() |
		GestureState.FAILED.toUint();
 
	private static var allStatesInitialized:Boolean;
 
 
	private var value:uint;
	private var name:String;
	private var validTransitionsBitMask:uint;
 
	{
		_initClass();
	}
 
 
	public function GestureState(value:uint, name:String)
	{
		if (allStatesInitialized)
		{
			throw new IllegalOperationError("You cannot create gesture states." +
			"Use predefined constats like GestureState.RECOGNIZED");
		}
 
		this.value = value;
		this.name = name;
	}
 
 
	private static function _initClass():void
	{
		IDLE.setValidNextStates(POSSIBLE);
		POSSIBLE.setValidNextStates(RECOGNIZED, BEGAN, FAILED);
		RECOGNIZED.setValidNextStates(IDLE);
		BEGAN.setValidNextStates(CHANGED, ENDED, CANCELLED);
		CHANGED.setValidNextStates(CHANGED, ENDED, CANCELLED);
		ENDED.setValidNextStates(IDLE);
		FAILED.setValidNextStates(IDLE);
		CANCELLED.setValidNextStates(IDLE);
 
		allStatesInitialized = true;
	}
 
 
	public function toString():String
	{
		return "GestureState." + name;
	}
 
 
	public function toUint():uint
	{
		return value;
	}
 
 
	private function setValidNextStates(...states):void
	{
		var mask:uint;
		for each (var state:GestureState in states)
		{
			mask = mask | state.value;
		}
		validTransitionsBitMask = mask;
	}
 
 
	gestouch_internal function canTransitionTo(state:GestureState):Boolean
	{
		return (validTransitionsBitMask & state.value) > 0;
	}
 
 
	gestouch_internal function get isEndState():Boolean
	{
		return (endStatesBitMask & value) > 0;
	}
}
Захотелось мне это сделать чуть-чуть покрасивее и попроизводительнее примерно таким образом:
Код AS3:
// GestureState.as
public static const IDLE:GestureState = new IdleGestureState(1 << 0);
 
// IdleGestureState.as
internal class IdleGestureState extends GestureState
{
	public function IdleGestureState(value:uint)
	{
		super(value, "IDLE");
	}
 
 
	override public function canTransitionTo(nextState:GestureState):Boolean
	{
		return nextState is PossibleGestureState;
	}
 
 
	// по необходимости
	override public function get isEndState():Boolean
	{
		return false;
	}
}
Но возникает RTE при попытке создания такого вот класса-наследника. Дело в том, что базовый класс GestureState на момент создания сабкласса ещё не совсем определён (т.к. сабкласс пытаемся создать для static поля базового).

Варианты решения:
1. public static var ...
2. public static function get ...
3. класс GestureStates, в котором в свою очередть прописаны константы.

Ни одно из решений не нравится. Может ещё есть какие-то трюки?