Using ActionScript

Before you start developing custom components, you should be familiar with basic ActionScript coding practices.

Using the package statement

You must define your ActionScript custom components within a package. The package reflects the directory location of your component within the directory structure of your application. To define the package structure, you include the package statement in your class definition, as the following example shows:

package myComponents 
{ 
    // Class definition goes here. 
}

Your package statement must wrap the entire class definition. If you write your ActionScript class file to the same directory as your other application files, you can leave the package name blank. However, as a best practice, you should store your components in a subdirectory, where the package name reflects the directory location. In this example, write your ActionScript class file to the directory myComponents, a subdirectory of your main application directory.

Formatters are a particular type of component. You might also create a subdirectory of your application’s root directory called myFormatters for all of your custom formatter classes. Each formatter class would then define its package statement, as the following example shows:

package myFormatters 
{ 
    // Formatter class definition goes here. 
}

If you create a component that is shared among multiple applications, or a component that might be used with third-party components, assign a unique package name to avoid naming conflicts. For example, you might prefix your package name with your company name, as in:

package Acme.myFormatters 
{ 
    // Formatter class definition goes here. 
}

When you reference a custom component from an MXML file, specify a namespace definition for the component that corresponds to its directory location and package name, as the following example shows:

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:MyComp="myFormatters.*">  
 
    <!-- Declare a formatter and specify formatting properties. --> 
    <MyComp:SimpleFormatter id="upperFormat" formatString="upper"/>      
        ... 
 
</s:Application>

If a formatter class is in a subdirectory of myFormatters, such as myFormatters/dataFormatters, the package statement is as follows:

package myFormatters.dataFormatters 
{ 
    // Formatter class definition goes here. 
}

You then specify the namespace definition for the component, as the following example shows:

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:MyComp="myFormatters.dataFormatters.*">  
 
    <!-- Declare a formatter and specify formatting properties. --> 
    <MyComp:SimpleFormatter id="upperFormat" formatString="upper"/> 
        ... 
 
</s:Application>

Using the import statement

You use the import statement to import any classes that your class requires. Importing adds a reference to the class so that you can access classes defined by the import. Classes that you import must be located in the ActionScript source path for your application.

You import the classes referenced by your custom component as part of its implementation, as the following example shows:

package myComponents 
{ 
    // Import necessary classes. 
    import mx.core.Container; 
    import mx.controls.Button; 
    // Import all classes in the mx.events package 
    import mx.events.*; 
 
    // Class definition goes here.  
 
    // You can now create an instance of a Container using this syntax: 
    private var myContainer:Container = new Container(); 
 
}

There is a distinct difference between including and importing in ActionScript. Including is copying lines of code from one ActionScript file into another. Files that you include must be located relative to the file performing the include, or use an absolute path. Importing is adding a reference to a class file or package so that you can access objects and properties defined by external classes.

For more information on including and importing, see Using ActionScript.

Using the class statement

You use the class statement to define your class name, and to specify its superclass, as the following example shows:

package myComponents 
{ 
    // Import necessary classes 
    import mx.core.Container; 
    import mx.controls.Button; 
    // Import all classes in the mx.events package 
    import mx.events.*; 
 
    // Class definition goes here. 
    public class MyButton extends Button { 
         
        // Define properties, constructor, and methods.     
     
    } 
}

The class definition of your component must be prefixed by the public keyword, or it cannot be used as an MXML tag. A file that contains a class definition can have one, and only one, public class definition, although it can have additional internal class definitions. Place any internal class definitions at the bottom of your source file below the closing curly brace of the package definition.

In a single ActionScript file, you can define only one class in the package. To define more than one class in a file, define the additional classes outside of the package body.

Note: The class definition is one of the few ActionScript constructs that you cannot use in an <fx:Script> block in an MXML file.

Defining the constructor

An ActionScript class must define a public constructor method, which initializes an instance of the class. The constructor has the following characteristics:

  • No return type.

  • Should be declared public.

  • Might have optional arguments.

  • Cannot have any required arguments if you use it as an MXML tag.

  • Calls the super() method to invoke the superclass’ constructor.

You call the super() method within your constructor to invoke the superclass’ constructor to initialize the inherited items from the superclass. The super() method should be the first statement in your constructor; otherwise, the inherited parts of the superclass might not be properly constructed. In some cases, you might want to initialize your class first, and then call super().

Note: If you do not define a constructor, the compiler inserts one for you and adds a call to super(). However, it is considered a best practice to write a constructor and to explicitly call super(), unless the class contains nothing but static members. If you define the constructor, but omit the call to super(), Flex automatically calls super() at the beginning of your constructor.

In the following example, you define a constructor that uses super() to call the superclass’ constructor:

package myComponents 
{ 
    // Import necessary classes 
    import mx.core.Container; 
    import mx.controls.Button; 
    // Import all classes in the mx.events package 
    import mx.events.*; 
 
    // Class definition goes here. 
    public class MyButton extends Button { 
         
        // Public constructor.  
        public function MyButton() 
        { 
            // Call the constructor in the superclass.  
            super(); 
        } 
        // Define properties and methods.     
     
    } 
}
Note: You cannot define a constructor for an MXML component. For more information, see About implementing IMXMLObject

Defining properties as variables

Properties let you define data storage within your class. You can define your properties as public, which means that they can be accessed by users of the class. You can also define properties as private, which means that they are used internally by the class, as the following example shows:

public class MyButton extends Button { 
 
    // Define private vars. 
    private var currentFontSize:Number; 
 
    // Define public vars.  
    public var maxFontSize:Number = 15; 
    public var minFontSize:Number = 5; 
}

Users of the class can access the public variables but not the private variables, as the following example shows:

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:MyComp="myControls.*"> 
 
    <MyComp:MyButton label="Submit" maxFontSize="30"/> 
</s:Application>

Although you can define your classes to use public properties, you may find it advantageous to define properties by using setter and getter methods. For more information, see Defining methods.

Note: You cannot override an inherited property defined by a variable, but you can override a property defined by setter and getter methods. You can reset the value of an inherited property defined by a variable. You typically reset it in the constructor of the subclass for an ActionScript component, or in an event handler for an MXML component because MXML components cannot define a constructor.

Defining properties as getters and setters

You can define properties for your components by using setter and getter methods. The advantage of getters and setters is that they isolate the variable from direct public access so that you can perform the following actions:

  • Inspect and validate any data written to the property on a write

  • Trigger events that are associated with the property when the property changes

  • Calculate a return value on a read

  • Allow a child class to override

To define getter and setter methods, precede the method name with the keyword get or set, followed by a space and the property name. The following example shows the declaration of a public property named initialCount, and the getter and setter methods that get and set the value of this property:

// Define internal private variable. 
private var _initialCount:uint = 42; 
 
// Define public getter. 
public function get initialCount():uint { 
    return _initialCount; 
} 
 
// Define public setter.  
public function set initialCount(value:uint):void { 
    _initialCount = value; 
}

By convention, setters use the identifier value for the name of the argument.

The variable that stores the property’s value cannot have the same name as the getter or setter. By convention, precede the name of the variables with one (_) or two underscores (__). In addition, Adobe recommends that you declare the variable as private or protected.

Users of the class can access the public property, as the following example shows:

<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    xmlns:MyComp="myControls.*" > 
 
    <MyComp:MyButton label="Submit" initialCount="24"/> 
</s:Application>

If the getter or setter overrides a getter or setter in a superclass, ensure that you include the override keyword, as the following example shows:

override public function get label():String {} 
override public function set label(value:String):void {}

Defining methods

Methods define the operations that your class can perform. You define methods in the body of the class. Your methods can override a method of a superclass, or define new functionality for your components.

If the method adds new functionality, you define it using the function keyword, as the following example shows:

public function myMethod():void { 
    // Method definition  
}

If you define this method as a public method, users of the class can call it.

You can also define private methods, as the following example shows:

private function internalMethod():void { 
    // Method definition  
}

Private methods are for internal use by the class, and cannot be called by users of the class.

If the method overrides a method in a superclass, you must include the override keyword and the signature of the method must exactly match that of the superclass method, as the following example shows:

override protected function createChildren():void { 
    // Method definition  
}

Your methods may take required or optional arguments. To make any of the arguments optional, assign default values to them, as the following example shows:

override public validate(value:Object = null,  
    supressEvents:Boolean = false):ValidationResultEvent { 
    // Method definition  
}

If the method takes a variable number of arguments, use the “...” syntax, as the following example shows:

function foo(n:Number, ... rest):void { 
    // Method definition  
}

Flex creates an Array called rest for the optional arguments. Therefore, you can determine the number of arguments passed to the method by using rest.length, and access the arguments by using rest[i].

Using the super keyword in a method override

You use the super keyword in a method override to invoke the corresponding method of the superclass. The super keyword has the following syntax:

super.methodName([arg1, ..., argN])

This technique is useful when you create a subclass method that adds behavior to a superclass method but also invokes the superclass method to perform its original behavior.

Note: Although Flex automatically calls the super() method in a constructor to execute the superclass’ constructor, you must call super.methodName() in a method override. Otherwise, the superclass’ version of the method does not execute.

Whether you call super.myMethod() within a method override depends on your application requirement, as follows:

  • Typically, you extend the existing functionality of the superclass method, so the most common pattern is to call super.myMethod() first in your method override, and then add your logic.

  • You might need to change something before the superclass method does its work. In this case, you might call super.myMethod() in the override after your logic.

  • In some method overrides, you might not want to invoke the superclass method at all. Only call super.myMethod() if and when you want the superclass to do its work.

  • Sometimes the superclass has an empty method that does nothing, which requires you to implement the functionality in the method. In this case, you should still call super.myMethod() because in a future version of Flex, that method might implement some functionality. For more information, see the documentation on each Flex class.

About the scope

Scoping is mostly a description of what the this keyword refers to at any given point in your application. In the main MXML application file, the file that contains the <s:Application> tag, the current scope is the Application object, and therefore the this keyword refers to the Application object.

In an ActionScript component, the scope is the component itself and not the application or other file that references the component. As a result, the this keyword inside the component refers to the component instance and not the Flex Application object.

Nonvisual ActionScript components do not have access to their parent application with the parentDocument property. However, you can access the top-level Application object by using the mx.core.Application.application property.

For more information on scope, see Using ActionScript.