Can you specify the function parameter as a static constant of the Class function?
Let's say I have my own event class and it has several types of events stored in a static constant:
package customEvents
{
public class
{
public static const DISAPPEAR_COMPLETELY:String = "disappearCompletely";
public static const SIT_DOWN:String = "sitDown";
public static const STAND_UP:String = "standUp";
public static const SAIL_TO_THE_MOON:String = "sailToTheMoon";
public static const GO_TO_SLEEP:String = "goToSleep";
public static const GO_SLOWLY:String = "goSlowly";
public function MyCustomEvent(type:String)
{
super(type);
}
}
}
Is there an easy way to check that type
passed to the constructor is one of the static constants of the class without checking for every value?
a source to share
To extend Dan R's answer, you can create a string event (like the way you did enumerations) like this:
import flash.utils.Dictionary;
import flash.utils.describeType;
import flash.utils.getQualifiedClassName;
public class StrictEvent
{
private static var VALID_EVENTS:Dictionary = new Dictionary();
public static function initEvents(inType:*):void {
var events:Object = {};
var description:XML = describeType(inType);
var constants:XMLList = description.constant;
for each(var constant:XML in constants) {
events[inType[constant.@name]] = true;
}
VALID_EVENTS[getQualifiedClassName(inType)] = events;
}
public function StrictEvent(type:String)
{
var className:String = getQualifiedClassName(this);
if(VALID_EVENTS[className][type]) {
// init
} else {
throw new Error("Error! " + type);
}
}
}
You can then define your own event class by extending the strict event class and calling initEvents in a static initializer. Here's your example using this method:
public class CustomEvent extends StrictEvent
{
public static const DISAPPEAR_COMPLETELY:String = "disappearCompletely";
public static const SIT_DOWN:String = "sitDown";
public static const STAND_UP:String = "standUp";
public static const SAIL_TO_THE_MOON:String = "sailToTheMoon";
public static const GO_TO_SLEEP:String = "goToSleep";
public static const GO_SLOWLY:String = "goSlowly";
public function CustomEvent(type:String) {
super(type);
}
{
initEvents(CustomEvent);
}
}
Now, every time it creates an event, it has to look for the event object and see if that type is in that object. This also means that you don't have to manually add all the constants to the initializer.
a source to share
While both of these answers offer different solutions for validating string values, they do not answer the question of whether values โโshould be validated. Which you need to do, at least because the values โโof the constants are themselves strings.
So the answer is no, if you are extending the Event anyway. Since this initial parameter must be a String (if you're extending Event), no matter how many levels of indirection you use, you still end up checking the arguments against a list of valid values. Passing to anything other than a string will throw a runtime error.
a source to share
Christian is faithful - and the question contains a somewhat ambiguous term. When you check the "types" of events, they are not data types, that is, objects of the class, they are simply string values โโthat pass according to the particular "taste" of the event to the listener object.
Personally, I don't think you need runtime type checking for events. If your code is trying to use an event constant that doesn't exist, like
obj.addEventListener(CustomEvent.TYPE_WHICH_DOES_NOT_EXIST, handlerMethod);
... you'll get a compiler error before your code is run. If you use original string values โโfor event types, then you still defeat the purpose of using event constants.
a source to share
There are several ways to attack:
- Use the enum method on types to ensure it is listed. The parameter in the constructor will no longer be a string, but an enumeration. See http://blog.petermolgaard.com/2008/11/02/actionscript-3-enums/ for a way to replicate enums in AS3.
- Use a static constructor in your class to populate the list of types in the ArrayCollection and use the .contains () method to check membership. (Possible implementation below)
Your code sample appears to be an event class. In this case, you cannot use the first option, since you do not want to change the signature of the constructor if you do not need it.
package customEvents
{
public class
{
private static var typeList:ArrayCollection;
public static const DISAPPEAR_COMPLETELY:String = "disappearCompletely";
public static const SIT_DOWN:String = "sitDown";
<... lines deleted ...>
public static const GO_SLOWLY:String = "goSlowly";
// static constructor
{
typeList = new ArrayCollection();
typeList.addItem(DISAPPEAR_COMPLETELY);
typeList.addItem(SIT_DOWN);
<... lines deleted ...>
typeList.addItem(GO_SLOWLY);
public function MyCustomEvent(type:String)
{
if (typeList.contains(type)
super(type);
else
throw new Error("Invalid type");
}
}
}
a source to share