views:

180

answers:

2

I've created a class that loads it's subclasses based on a name passed to it. The function uses getDefinitionByName, gets the class type, and instantiates it, and returns it if the class is a subtype of the class that owns this method. The subtypes are all mxml files that extend the base class, in order to simplify instantiating controls.

However, in the case where I pass it a fully qualified name, it works in my unit tests but fails when I execute it in the context of my application. Is there a gotcha in getDefinitionByName that makes it behave differently in different execution contexts? Is there a simpler way to load classes by their qualified name?

static public function loadDisplay(className:String, extendedClassName:String = null):FeatureDisplay
{
 try
 {
  trace("Loading", className);
  var cls:Class = getDefinitionByName(className) as Class;
  var display:FeatureDisplay = new cls() as FeatureDisplay;
  if(display)
  {
   return display;
  }
  else
  {
   trace(className, "is not a subclass of FeatureDisplay");
   return null;
  }
 }
 catch(error:Error)
 {
  trace("Error loading", className);
  trace("Error:", error.message);
 }
 return null;
}
+3  A: 

My first question is are you explicitly using any of the classes anywhere? If you do not actually use a class, even if it is imported, ActionScript may not end up keeping a copy of the class's definition in the swf.

That said, you're better off avoiding getDefinitionByName, describeType, getQualifiedClassName or getQualifiedSuperclassName if you can possibly avoid them. They are memory hogs and it is generally best to avoid them. (unless you do not have control over which classes will be used at run time and they HAVE to be used through getDefinitionByName).

My suggestion is that you replace getQualifiedClassName with a swtich...case:

// Import the subclasses.
import path.to.SpriteFeatureDisplay;
import path.to.OtherFeatureDisplay;

class FeatureDisplay extends Sprite{

   //Make one public static const per class.
   public static const SPRITE_FEATURE_DISPLAY:String = "sprite_feature_display";
   public static const OTHER_FEATURE_DISPLAY:String  = "other_feature_display";

   public static function loadDisplay(  className:String, 
                                        extName:String = null ):FeatureDisplay
   {
      trace("Loading", className);

      // This will ensure that each of the classes is stored in the swf
      // it will behave faster, and it is less prone to errors (note that 
      // try...catch is not needed).
      swtich( className )
      {
    case SPRITE_FEATURE_DISPLAY:
   return new SpriteFeatureDisplay();
    case OTHER_FEATURE_DISPLAY:
   return new OtherFeatureDisplay();
    default:
   trace( "Requested class " + className + " could not be created..." +
   "\nPlease make sure that it is a subclass of FeatureDisplay" );
   return null;
      }
      return null;
   }
}
Christopher W. Allen-Poole
It looks like you got it - the unit tests explicitly referenced the type to make sure the right one was produced, and the application code didn't.
Dan Monego
+2  A: 

FYI, I've seen the following method of keeping classes used in Flex's source code:

// References.cs

// notice the double reference: one to import, the other to reference
import package.to.ClassA; ClassA;
import package.to.ClassB; ClassB;
import package.to.ClassC; ClassC;

Of course, you still have to reference the "References" class somewhere.

Richard Szalay