Methods



Methods are functions that are part of a class definition. Once an instance of the class is created, a method is bound to that instance. Unlike a function declared outside a class, a method cannot be used apart from the instance to which it is attached.

Methods are defined using the function keyword. As with any class property, you can apply any of the class property attributes to methods, including private, protected, public, internal, static, or a custom namespace.You can use a function statement such as the following:

public function sampleFunction():String {}

Or you can use a variable to which you assign a function expression, as follows:

public var sampleFunction:Function = function () {}

In most cases you will want to use a function statement instead of a function expression for the following reasons:

  • Function statements are more concise and easier to read.

  • Function statements allow you to use the override and final keywords. For more information, see Overriding methods.

  • Function statements create a stronger bond between the identifier—that is, the name of the function—and the code within the method body. Because the value of a variable can be changed with an assignment statement, the connection between a variable and its function expression can be severed at any time. Although you can work around this issue by declaring the variable with const instead of var, such a technique is not considered a best practice, because it makes the code hard to read and prevents the use of the override and final keywords.

One case in which you must use a function expression is when you choose to attach a function to the prototype object. For more information, see The prototype object.

Constructor methods

Constructor methods, sometimes simply called constructors, are functions that share the same name as the class in which they are defined. Any code that you include in a constructor method is executed whenever an instance of the class is created with the new keyword. For example, the following code defines a simple class named Example that contains a single property named status. The initial value of the status variable is set inside the constructor function.

class Example 
{ 
    public var status:String; 
    public function Example() 
    { 
        status = "initialized"; 
    } 
} 
 
var myExample:Example = new Example(); 
trace(myExample.status); // output: initialized

Constructor methods can only be public, but the use of the public attribute is optional. You cannot use any of the other access control specifiers, including private, protected, or internal, on a constructor. You also cannot use a user-defined namespace with a constructor method.

A constructor can make an explicit call to the constructor of its direct superclass by using the super() statement. If the superclass constructor is not explicitly called, the compiler automatically inserts a call before the first statement in the constructor body. You can also call methods of the superclass by using the super prefix as a reference to the superclass. If you decide to use both super() and super in the same constructor body, be sure to call super() first. Otherwise, the super reference will not behave as expected. The super() constructor should also be called before any throw or return statement.

The following example demonstrates what happens if you attempt to use the super reference before calling the super() constructor. A new class, ExampleEx, extends the Example class. The ExampleEx constructor attempts to access the status variable defined in its superclass, but does so before calling super(). The trace() statement inside the ExampleEx constructor produces the value null, because the status variable is not available until the super() constructor executes.

class ExampleEx extends Example 
{ 
    public function ExampleEx() 
    { 
        trace(super.status); 
        super(); 
    } 
} 
 
var mySample:ExampleEx = new ExampleEx(); // output: null

Although it is legal to use the return statement inside a constructor, it is not permissible to return a value. In other words, return statements must not have associated expressions or values. Accordingly, constructor methods are not allowed to return values, which means that no return type may be specified.

If you do not define a constructor method in your class, the compiler will automatically create an empty constructor for you. If your class extends another class, the compiler will include a super() call in the constructor it generates.

Static methods

Static methods, also called class methods, are methods that are declared with the static keyword. Static methods, which are attached to a class rather than to an instance of a class, are useful for encapsulating functionality that affects something other than the state of an individual instance. Because static methods are attached to a class as a whole, static methods can be accessed only through a class and not through an instance of the class.

Static methods are useful for encapsulating functionality that is not limited to affecting the state of class instances. In other words, a method should be static if it provides functionality that does not directly affect the value of a class instance. For example, the Date class has a static method named parse(), which takes a string and converts it to a number. The method is static because it does not affect an individual instance of the class. Instead, the parse() method takes a string that represents a date value, parses the string, and returns a number in a format compatible with the internal representation of a Date object. This method is not an instance method, because it does not make sense to apply the method to an instance of the Date class.

Contrast the static parse() method with one of the instance methods of the Date class, such as getMonth(). The getMonth() method is an instance method, because it operates directly on the value of an instance by retrieving a specific component, the month, of a Date instance.

Because static methods are not bound to individual instances, you cannot use the keywords this or super within the body of a static method. Both the this reference and the super reference have meaning only within the context of an instance method.

In contrast with some other class-based programming languages, static methods in ActionScript 3.0 are not inherited. For more information, see Static properties not inherited.

Instance methods

Instance methods are methods that are declared without the static keyword. Instance methods, which are attached to instances of a class instead of the class as a whole, are useful for implementing functionality that affects individual instances of a class. For example, the Array class contains an instance method named sort(), which operates directly on Array instances.

Within the body of an instance method, both static and instance variables are in scope, which means that variables defined in the same class can be referenced using a simple identifier. For example, the following class, CustomArray, extends the Array class. The CustomArray class defines a static variable named arrayCountTotal to track the total number of class instances, an instance variable named arrayNumber that tracks the order in which the instances were created, and an instance method named getPosition() that returns the values of these variables.

public class CustomArray extends Array 
{ 
    public static var arrayCountTotal:int = 0; 
    public var arrayNumber:int; 
 
    public function CustomArray() 
    { 
        arrayNumber = ++arrayCountTotal; 
    } 
     
    public function getArrayPosition():String 
    { 
         return ("Array " + arrayNumber + " of " + arrayCountTotal); 
    } 
}

Although code external to the class must refer to the arrayCountTotal static variable through the class object using CustomArray.arrayCountTotal, code that resides inside the body of the getPosition() method can refer directly to the static arrayCountTotal variable. This is true even for static variables in superclasses. Though static properties are not inherited in ActionScript 3.0, static properties in superclasses are in scope. For example, the Array class has a few static variables, one of which is a constant named DESCENDING. Code that resides in an Array subclass can refer to the static constant DESCENDING using a simple identifier:

public class CustomArray extends Array 
{ 
    public function testStatic():void 
    { 
        trace(DESCENDING); // output: 2 
    } 
}

The value of the this reference within the body of an instance method is a reference to the instance to which the method is attached. The following code demonstrates that the this reference points to the instance that contains the method:

class ThisTest 
{ 
    function thisValue():ThisTest 
    { 
        return this; 
    } 
} 
 
var myTest:ThisTest = new ThisTest(); 
trace(myTest.thisValue() == myTest); // output: true

Inheritance of instance methods can be controlled with the keywords override and final. You can use the override attribute to redefine an inherited method, and the final attribute to prevent subclasses from overriding a method. For more information, see Overriding methods.

Get and set accessor methods

Get and set accessor functions, also called getters and setters, allow you to adhere to the programming principles of information hiding and encapsulation while providing an easy-to-use programming interface for the classes that you create. Get and set functions allow you to keep your class properties private to the class, but allow users of your class to access those properties as if they were accessing a class variable instead of calling a class method.

The advantage of this approach is that it allows you to avoid the traditional accessor functions with unwieldy names, such as getPropertyName() and setPropertyName(). Another advantage of getters and setters is that you can avoid having two public-facing functions for each property that allows both read and write access.

The following example class, named GetSet, includes get and set accessor functions named publicAccess() that provide access to the private variable named privateProperty:

class GetSet 
{ 
    private var privateProperty:String; 
     
    public function get publicAccess():String 
    { 
        return privateProperty; 
    } 
     
    public function set publicAccess(setValue:String):void 
    { 
        privateProperty = setValue; 
    } 
}

If you attempt to access the property privateProperty directly, an error will result, as follows:

var myGetSet:GetSet = new GetSet(); 
trace(myGetSet.privateProperty); // error occurs

Instead, a user of the GetSet class will use something that appears to be a property named publicAccess, but that is really a pair of get and set accessor functions that operate on the private property named privateProperty. The following example instantiates the GetSet class, and then sets the value of the privateProperty using the public accessor named publicAccess:

var myGetSet:GetSet = new GetSet(); 
trace(myGetSet.publicAccess); // output: null 
myGetSet.publicAccess = "hello"; 
trace(myGetSet.publicAccess); // output: hello

Getter and setter functions also make it possible to override properties that are inherited from a superclass, something that is not possible when you use regular class member variables. Class member variables that are declared using the var keyword cannot be overridden in a subclass. Properties that are created using getter and setter functions, however, do not have this restriction. You can use the override attribute on getter and setter functions that are inherited from a superclass.

Bound methods

A bound method, sometimes called a method closure, is simply a method that is extracted from its instance. Examples of bound methods include methods that are passed as arguments to a function or returned as values from a function. New in ActionScript 3.0, a bound method is similar to a function closure in that it retains its lexical environment even when extracted from its instance. The key difference, however, between a bound method and a function closure is that the this reference for a bound method remains linked, or bound, to the instance that implements the method. In other words, the this reference in a bound method always points to the original object that implemented the method. For function closures, the this reference is generic, which means that it points to whatever object the function is associated with at the time it is invoked.

Understanding bound methods is important if you use the this keyword. Recall that the this keyword provides a reference to a method’s parent object. Most ActionScript programmers expect that the this keyword always refers to the object or class that contains the definition of a method. Without method binding, however, this would not always be true. In previous versions of ActionScript, for example, the this reference did not always refer to the instance that implemented the method. When methods are extracted from an instance in ActionScript 2.0, not only is the this reference not bound to the original instance, but also the member variables and methods of the instance’s class are not available. This is not a problem in ActionScript 3.0, because bound methods are automatically created when you pass a method as a parameter. Bound methods ensure that the this keyword always references the object or class in which a method is defined.

The following code defines a class named ThisTest, which contains a method named foo() that defines the bound method, and a method named bar() that returns the bound method. Code external to the class creates an instance of the ThisTest class, calls the bar() method, and stores the return value in a variable named myFunc.

class ThisTest 
{ 
    private var num:Number = 3; 
    function foo():void // bound method defined 
    { 
        trace("foo's this: " + this); 
        trace("num: " + num); 
    } 
    function bar():Function 
    { 
        return foo; // bound method returned 
    } 
} 
 
var myTest:ThisTest = new ThisTest(); 
var myFunc:Function = myTest.bar(); 
trace(this); // output: [object global] 
myFunc(); 
/* output:  
foo's this: [object ThisTest] 
output: num: 3 */

The last two lines of code show that the this reference in the bound method foo() still points to an instance of ThisTest class, even though the this reference in the line just before it points to the global object. Moreover, the bound method stored in the myFunc variable still has access to the member variables of the ThisTest class. If this same code is run in ActionScript 2.0, the this references would match, and the num variable would be undefined.

One area where the addition of bound methods is most noticeable is with event handlers, because the addEventListener() method requires that you pass a function or method as an argument. For more information, see Listener function defined as a class method in Event listeners.