Mar
Mar

Reputation: 323

Actionscript, can a class be accessed using a variable name?

I wish to access many classes and variables, I would like to do this by dynamically setting the class name and variable name. Currently I am using

MyClass["myVariable1"]

to dynamically access the variable name

MyClass.myVariable1

I want to also dynanmically acces the class name, something like

["MyClass"]["myVariable1"]

But this does not work.

The purpose is that I have shared object with many user settings, I want to iterate through the shared object and set all the user settings across all the classes. I think if I cant dynamically access the class I must have a statement for each and every class name/variable.

Upvotes: 1

Views: 73

Answers (2)

Organis
Organis

Reputation: 7316

I advise against such a practice. Although technically possible, it is like welcoming a disaster into the app architecture:

  1. You rely on something you have no apparent control of: on the way Flash names the classes.

  2. You walk out of future possibility to protect your code with identifier renaming obfuscation because it will render your code invalid.

  3. Compile time error checks is better than runtime, and you are leaving it to runtime. If it happens to fail in non-debug environment, you will never know.

  4. The next developer to work with your code (might be you in a couple of years) will have hard time finding where the initial data coming from.

So, having all of above, I encourage you to switch to another model:

package
{
    import flash.net.SharedObject;

    public class SharedData
    {
        static private var SO:SharedObject;

        static public function init():void
        {
            SO = SharedObject.getLocal("my_precious_shared_data", "/");
        }

        static public function read(key:String):*
        {
            // if (!SO) init();
            return SO.data[key];
        }

        static public function write(key:String, value:*):void
        {
            // if (!SO) init();
            SO.data[key] = value;
            SO.flush();
        }

        // Returns stored data if any, or default value otherwise.
        // A good practice of default application values that might
        // change upon user activity, e.g. sound volume or level progress.
        static public function readSafe(key:String, defaultValue:*):*
        {
            // if (!SO) init();
            return SO.data.hasOwnProperty(key)? read(key): defaultValue;
        }
    }
}

In the main class you call

SharedData.init();
// So now your shared data are available.
// If you are not sure you can call it before other classes will read
// the shared data, just uncomment // if (!SO) init(); lines in SharedData methods.

Then each class that feeds on these data should have an initialization block:

// It's a good idea to keep keys as constants
// so you won't occasionally mistype them.
// Compile time > runtime again.
static private const SOMAXMANA:String = "maxmana";
static private const SOMAXHP:String = "maxhp";

private var firstTime:Boolean = true;

private var maxmana:int;
private var maxhp:int;

// ...

if (firstTime)
{
    // Make sure it does not read them second time.
    firstTime = false;

    maxhp = SharedData.readSafe(SOMAXHP, 100);
    maxmana = SharedData.readSafe(SOMAXMANA, 50);
}

Well, again. The code above:

  • does not employ weird practices and easy to understand
  • in each class anyone can clearly see where the data come from
  • will be checked for errors at compile time
  • can be obfuscated and protected

Upvotes: 3

influjensbahr
influjensbahr

Reputation: 4078

You can try getting the class into a variable and going from there:

var myClass:Class = getDefinitionByName("MyClass") as Class;
myClass["myVariable1"] = x;

Upvotes: 2

Related Questions