2009-05-22 12 views
0

Lassen Sie sich sagen, dass ich eine benutzerdefinierte Event-Klasse, und es hat Typen mehr Ereignisse in statischer Konstante gespeichert:Können Sie verlangen, dass ein Funktionsparameter eine statische Konstante der Klasse der Funktion ist?

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); 
     } 
    } 
} 

Gibt es eine einfache Möglichkeit, zu überprüfen, ob die type an den Konstruktor übergab eine der statischen Konstanten ist von die Klasse, ohne sie gegen jeden Wert zu überprüfen?

Antwort

0

Wenn Sie für jede der statischen Konstanten als Klein Strings der Groß- konstanten Namen machen wäre, dann könnten Sie tun:

if(class.hasOwnProperty(type.toUpperCase())) 
{ 
    // Do something 
} 
else 
{ 
    // Failure 
} 
0

Es gibt ein paar Möglichkeiten, wie Sie diese angreifen kann:

  1. Verwenden Sie einen Enum-Ansatz für die Typen, um sicherzustellen, dass sie in der Liste enthalten ist. Der Parameter im Konstruktor wäre nicht länger eine Zeichenfolge, sondern eine Enumeration. Eine Möglichkeit zum Replizieren von Enums in AS3 finden Sie unter http://blog.petermolgaard.com/2008/11/02/actionscript-3-enums/.
  2. Verwenden Sie einen statischen Konstruktor in Ihrer Klasse, um die Liste der Typen in eine ArrayCollection aufzufüllen, und verwenden Sie die .contains() -Methode, um nach einer Mitgliedschaft zu suchen. (Mögliche Implementierung unten)

Ihr Codebeispiel scheint eine Ereignisklasse zu sein. Wenn das der Fall ist, können Sie die erste Option nicht verwenden, da Sie die Signatur des Konstruktors nicht ändern möchten, wenn dies nicht erforderlich ist.

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"); 
     } 
    } 
} 
1

off Antwort des von Dan R zu verlängern, könnten Sie ein strenges Ereignis (wie die Art und Weisen Sie Aufzählungen tun würden) schaffen Klasse wie folgt: Dann

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[[email protected]]] = 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); 
     } 
    } 


    } 

, könnten Sie Ihr benutzerdefiniertes Ereignis definieren Klasse, indem Sie die strikte Ereignisklasse erweitern und initEvents im statischen Initialisierer aufrufen. Hier ist dein Beispiel mit dieser Methode:

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); 
    } 

} 

Nun, jedes Mal schafft ein Ereignis hat es nur das Ereignisobjekt suchen und sehen, ob der Typ in diesem Objekt ist. Es bedeutet auch, dass Sie nicht alle Konstanten im Initialisierer manuell hinzufügen müssen.

1

Während beide Antworten verschiedene Lösungen zur Überprüfung der Zeichenfolgenwerte bieten, beantworten sie nicht die Frage mit, um die Werte zu überprüfen. Was Sie tun müssen, zumindest weil die Werte der Konstanten Strings selbst sind.

Also die Antwort ist nein - nicht, wenn Sie Event sowieso verlängern. Da dieser Anfangsparameter ein String sein muss (sofern Sie Event verlängern), werden Sie immer noch die Argumente gegen eine Liste gültiger Werte überprüfen, egal wie viele Ebenen der Indirektion Sie verwenden. Wenn Sie etwas anderes als einen String übergeben, wird ein Laufzeitfehler ausgelöst.

+0

Ich denke, er stellt die Frage, ob Sie JEDEN einen O (N) überprüfen müssen, im Gegensatz zum Überprüfen eines Hash-O (1). – mweiss

1

Christian ist richtig - und die Frage enthält einen etwas zweideutigen Begriff. Wenn Sie nach "Ereignistypen" suchen, sind sie keine Datentypen, d. H. Klassenobjekte, sie sind einfach Zeichenfolgenwerte, die den bestimmten "Geschmack" des Ereignisses an das hörende Objekt weitergeben.

Persönlich glaube ich nicht, dass Sie Laufzeitvalidierung von Ereignistypen benötigen.Wenn Ihr Code versucht, ein Ereignis Konstante zu verwenden, die nicht existiert, wie

obj.addEventListener(CustomEvent.TYPE_WHICH_DOES_NOT_EXIST, handlerMethod); 

... Sie gehen einen Compiler-Fehler erhalten, bevor der Code selbst ausgeführt werden. Wenn Sie rohe Zeichenfolgewerte für Ereignistypen verwenden, werden Sie den Zweck der Verwendung von Ereigniskonstanten sowieso vereiteln.

+0

Um Teufels Advokat zu spielen, was, wenn CustomEvent.TYPE_WHICH_DOES_NOT_EXIST stattdessen durch eine Variable ersetzt wird, die auf eine weniger einfache Weise bestimmt wird? – mweiss

+0

@mweiss, wie in einem einfachen String-Wert? Der schlimmste Fall ist, dass Sie niemals ein Ereignis hören werden, daher wird Ihr Handler niemals ausgeführt. –

+0

Sie könnten eine Variable anstelle der Ereignistyp-Konstante verwenden, aber irgendwo auf dem Weg müssen Sie einen Wert an diese Variable übergeben, bevor Sie den Listener deklarieren. Wenn dieser Wert eine Typkonstante ist, die nicht existiert, erhalten Sie immer noch einen Kompilierungsfehler. Wenn dieser Wert eine gerade Zeichenfolge ist, verwenden Sie keine Ereignisse korrekt. Ereignistyp-Konstanten sind nur Variablen, die die Zeichenfolgenwerte der verschiedenen Ereignisse enthalten, um die Typüberprüfung beim Kompilieren zu ermöglichen. – Joeflash