Table of Contents

Object.addProperty Method Flash 6

define a getter/setter property for an object or class
someObject.addProperty(propertyName, getterFunction, setterFunction)

Arguments

propertyName

A string indicating the name of the property to add. The name must adhere to the rules for creating an identifier, outlined under Section 15.5 in Chapter 15.

getterFunction

A "getter" function that returns propertyName's current value. By convention, it should be named getPropertyName, where PropertyName matches the propertyName parameter. It can be either a custom function or a built-in method of the object, as shown under the following Example.

setterFunction

A "setter" function, expected to set the value of propertyName internally. By convention, it should be named setPropertyName, where PropertyName matches the propertyName parameter. It can be either a custom function or a built-in method of the object, as shown under the following Example. Use null for setterFunction when the property is read-only.

Returns

A Boolean; true if the operation was successful, false if propertyName is not a valid identifier or if either getterFunction or setterFunction is not a function object.

Description

The addProperty( ) method defines a so-called "getter/setter" property, named propertyName, on someObject. A getter/setter property behaves ostensibly like a regular property, except that retrieval and assignment of its value is handled automatically by the two functions: getterFunction and setterFunction. This allows developers to provide convenient property-style access to complex operations. When someObject.propertyName is used in any expression (except on the left side of an assignment operation), the interpreter must determine and return the property's value. To do so, the interpreter executes the function specified by getterFunction, and its return value is used as propertyName's value. For example:

// Create an object.
var gamePlayer = new Object();
// Add the getter/setter property. We make the property read-only by
// using null for the setFunction parameter.
gamePlayer.addProperty("score", getScore, null);
// Define the function to execute when gamePlayer.score's value is read.
// This isn't a realistic example, but see the next example for realistic usage.
function getScore () {
  return 1500;
}
// Read gamePlayer.score, which automatically calls the getScore() function
// and uses its return value (1500) as the value to print in the Output window.
trace(gamePlayer.score);

When someObject.propertyName is used on the left side of an assignment operation (on the left of the equals sign), the interpreter must set the property's value. To do so, the interpreter executes the function specified by setterFunction, passing it the new value (as specified in the property assignment statement) as an argument. Often, the argument is simply stored internally for later retrieval by the getterFunction. For example:

// Create an object.
var gamePlayer = new Object();
// Add the getter/setter property, this time specifying setScore() as the
// function to execute when gamePlayer.score is written.
gamePlayer.addProperty("score", getScore, setScore);
// Here's our getterFunction (a.k.a., the "getter").
function getScore () {
  return gamePlayer.currentScore;
}
// Here's our setterFunction (a.k.a., the "setter"). The newly assigned 
// property value is passed in as the only parameter, which we call newVal.
function setScore (newVal) {
  // Store the assigned property value internally in a separate property
  // for later retrieval by getScore().
  gamePlayer.currentScore = newVal;
}
gamePlayer.score = 2000;  // Here, setScore() is invoked with a newVal of 2000.
trace(gamePlayer.score);  // Here, getScore() is invoked. Displays: 2000
// Just to prove it's working behind the scenes, check the
// internal currentScore property value.
trace(gamePlayer.currentScore);  // Displays: 2000

The value passed to the setterFunction must not be written into a property with the same name as propertyName.

The following code mistakenly assigns newVal to score, which collides with the getter/setter property of the same name:

function setScore (newVal) {
  // OOPS! THIS BREAKS THE GETTER/SETTER PROPERTY!
  gamePlayer.score = newVal;
}

To remove a getter/setter property, simply delete it and the supporting getter/setter functions, as in:

delete someObject.propertyName
delete getterFunc;
delete setterFunc;

Getter/setter properties normally are used when a property value must be calculated internally by a method, or when the exposed property value differs from the value stored internally by the class. For example, suppose we want to define a Ball object's color property. Externally, we want color to use the natural language string values "blue", "red", and "green". But internally we want our color property value to be stored as an RGB integer. We want the color property to be set like this:

redBall.color = "red";

But we want to store the equivalent of "red" internally as 0xFF0000. And when the value of redBall.color is retrieved, we must internally convert the number 0xFF0000 back to the string "red". Here's how we create our natural language color property as a getter/setter:

// Create the Ball class constructor.
function Ball () {
  // Create the setter method for the color property.
  this.setColor = function (newVal) {
    // Convert the assigned value to lowercase.
    var theColor = newVal.toLowerCase();
    // Convert the natural name to an equivalent number, and store
    // it internally in the property colorNum.
    if (theColor =  = "red") {
      this.colorNum = 0xFF0000;
    } else if (theColor =  = "green") {
      this.colorNum = 0x00FF00;
    } else if (theColor =  = "blue") {
      this.colorNum = 0x0000FF;
    } else {
      // If the color specified isn't red, green, or blue, use black.
      this.colorNum = 0x000000;
    }
  }
   
  // Create the getter method for the color property.
  this.getColor = function () {
    // Convert the internal colorNum property to its equivalent natural
    // name, and return the name as the value of the color property.
    if (this.colorNum =  = 0xFF0000) {
      return "red";
    } else if (this.colorNum =  = 0x00FF00) {
      return "green";
    } else if (this.colorNum =  = 0x0000FF) {
      return "blue";
    } else {
      return "black";
    }
  }
   
  // Add the getter/setter color property.
  this.addProperty("color", this.getColor, this.setColor);
}
   
// Create a ball instance.
redBall = new Ball();
   
// Assign our ball a color. Note that the setter function accepts
// any mixture of uppercase and lowercase letters in the color name.
redBall.color = "RED";
// Check the color now. The getter function always returns lowercase names.
trace(redBall.color);  // Displays: red

Notice that the getter and setter functions are invoked as methods of the object containing the getter/setter property, so they can refer to the object as this and access its properties and methods. So far, however, this code is inefficient because it assigns the setColor( ) and getColor( ) methods directly to every instance of Ball. Luckily, getter/setter properties can be added to a class constructor's prototype property, where a class's methods are normally defined. Here's the improved version of our color getter/setter property, attaching method and property definitions to prototype:

// The Ball class
function Ball () {
  // Instance initialization code goes here...
}
   
// The setter function
Ball.prototype.setColor = function (newVal) {
  var theColor = newVal.toLowerCase();
  if (theColor =  = "red") {
    this.colorNum = 0xFF0000;
  } else if (theColor =  = "green") {
    this.colorNum = 0x00FF00;
  } else if (theColor =  = "blue") {
    this.colorNum = 0x0000FF;
  } else {
    this.colorNum = 0x000000;
  }
}
   
// The getter function
Ball.prototype.getColor = function () {
  if (this.colorNum =  = 0xFF0000) {
    return "red";
  } else if (this.colorNum =  = 0x00FF00) {
    return "green";
  } else if (this.colorNum =  = 0x0000FF) {
    return "blue";
  } else {
    return "black";
  }
}
   
// The getter/setter color property, defined on Ball.prototype
Ball.prototype.addProperty("color",
                           Ball.prototype.getColor,
                           Ball.prototype.setColor);
   
// Create a ball instance
redBall = new Ball();
   
// Assign and check our ball's color
redBall.color = "RED";
trace(redBall.color);  // Displays: red

Note that getter/setter properties are used entirely for convenience. It is perfectly legitimate to expose getter and setter methods directly, without providing getter/setter property access to the values they manipulate. For example, our Ball class could simply require the direct use of the setColor( ) and getColor( ) methods rather than providing the color getter/setter property. Conversely, it is legitimate in ActionScript, though considered poor object-oriented programming (OOP) practice, to access the internal colorNum directly. That is, one could retrieve and assign the colorNum property as redBall.colorNum, to avoid or bypass getter and setter functions altogether.

Bugs

In Flash 6, getter/setter properties cannot be added directly to the _global object. They can, however, be added to objects defined on the _global object.

Example

The following nifty code—suggested by Guy Watson of http://www.flashguru.co.uk—creates a getter/setter depth property for all movie clips. It provides an interface that's easier to use and remember than the built-in getDepth( ) and swapDepths( ) methods:

// Add the property.
MovieClip.prototype.addProperty("depth",
                                MovieClip.prototype.getDepth,
                                MovieClip.prototype.swapDepths);
   
// Try it out. Note that swapDepths( ) can accept either a number or a target clip.
this.createEmptyMovieClip("empty_mc", 15);
trace(empty_mc.depth);     // Displays: 15
empty_mc.depth = 20;       // Pass an integer to swapDepths(). Depth becomes 20.
trace(empty_mc.depth);     // Displays: 20
empty_mc.depth = ball_mc;  // Trade depths with ball_mc (passed to swapDepths())

See Also

MovieClip.getDepth( ), MovieClip.swapDepths( ), Object._ _proto_ _, Object.watch( ); Chapter 12


Table of Contents