Defining Members

Not all class members are created equal. Using special keywords, members can be configured in various ways, allowing you to specify how the member is accessed and the scope of its influence. Next, we'll discuss what this means and how you can use this functionality when creating class members.

Public and Private Members

By default, all members of a class (its properties and methods) are public. This means that the property or methods of that class can be accessed by instances of that class. Look again at our State class definition:


class State {

  var statePopulation:Number;

  function State() {

    //Constructor

  }

  function setPopulation(num:Number) {

    statePopulation = num + (num * .05);

  }

  function getPopulation():Number {

    return statePopulation;

  }

}


The members in this class, statePopulation, setPopulation(), and getPopulation(), are all publicly accessible by instances of the class. For example, the following script:


northCarolina.statePopulation = 8000000;


shows us setting the value of statePopulation directly. As mentioned in the preceding section, while this property is used to hold a numeric value representing the state's population, it's better to use getter and setter methods to get and set the value, which our class definition has been set up to do. In other words, statePopulation should be a variable that cannot be directly accessed from outside the class definition. To make this change, you use the private and public keywords to indicate each member's access in a class:


class State {

  private var statePopulation:Number;

  function State() {

    //Constructor

  }

  public function setPopulation(num:Number) {

    statePopulation = num + (num * .05);

  }

  public function getPopulation():Number {

    return statePopulation;

  }

}


statePopulation has been declared as a private member of the class. As a result, only code within the class definition itself, such as the setPopulation() and getPopulation() methods, can access it directly. Attempting to access it from an instance in the following way:


northCarolina.statePopulation = 8000000;


results in an error.

Any property or method can be declared private or public, as you see fit.

graphics/07inf10.gif

Why would you want to hide some members in this way? Because a robust class definition often has many properties and methods that are used to take care of tasks internally; they have functionality built into them that should not be exposed for use outside the class. Let's look at a real-world example.

When most people use a computer, all they want to know is how to turn it on and off, and how to interact with it via the keyboard and mouse. Most people aren't interested in knowing how it works internally (information about how the hardware is sending data through the circuits or the way the hard drive is reading and writing datathe internal workings of the computer that are important, but that don't affect how it's used). In the same sense, it's not necessary to open all the functionalities of a class to direct access from an instance of that class. A class may have 10 properties and 15 methods internally that affect how instances of that class work, but maybe only 3 or 4 methods that should be directly referenced from an instance.

In the long run, setting member access helps prevent bugs because, as mentioned earlier, it prevents you from scripting an object in a way that you shouldn't. If you attempt to use an object in the wrong way (attempting to use or access a private class member that should only be used internally, within the class), Flash displays an error and lets you know that you need to reexamine your code.

Static Members

By default, every member of a class is duplicated within an instance whenever that instance is created. Consider the State class example that we've used a few times in this lesson. For every new instance of that class, a copy of the statePopulation property is created within the instance. This makes sense because every state has its own population. In other words, while every instance of the State class has a statePopulation property, the value of that property may differ for each instance.

There may be circumstances, however, when you need a property that is not only accessible by every instance of a class, but has a universal value across all instances. This is the functionality that static properties provide.

If a property is static, it's created in memory only once. All instances of the class see the same copy of this member. If any instance of the class edits the value of the property, all instances of the class see the new value.

Take the following class as an example:


class Star {

  static var starsInTheSky:Number = 1000000000;

  function Star() {

    //Constructor

  }

  function setTotalStars(num:Number) {

    starsInTheSky = num;

  }

  function getTotalStars():Number {

    return starsInTheSky;

  }

}


The property starsInTheSky has been specified as static, and is used to store the total number of stars that can be seen in the sky. If we were to create several instances of this class, as follows:


var star1:Star = new Star();

var star2:Star = new Star();

var star3:Star = new Star();


referencing the starsInTheSky property from any one of these instances would result in the same value:


star1.starsInTheSky //has a value of 1000000000

star2.starsInTheSky //has a value of 1000000000

star3.starsInTheSky //has a value of 1000000000


If a star goes supernova or another star is born, the setTotalStars() method can be executed to change the value of starsInTheSky. When the value is changed, say to 1000000037, all Star class instances see the following new value:


star1.starsInTheSky //has a value of 1000000037

star2.starsInTheSky //has a value of 1000000037

star3.starsInTheSky //has a value of 1000000037


NOTE

Yes, we're using code that directly accesses a property (something we told you earlier not to do). This is done strictly to demonstrate the universality of static members.


When would this kind of functionality be useful? Imagine having a class in which each instance has to load data from the same URL. If the URL was created as a static property of the class, it could be changed at a later time and all of the instances would automatically load from the new URL.

Methods can be static, too. Take a look at the following example:


class Sky {

  static var starsInTheSky:Number = 1000000000;

  static function setTotalStars(num:Number) {

    starsInTheSky = num;

  }

  static function getTotalStars():Number {

    return starsInTheSky;

  }

}


This class has the starsInTheSky static property and two static methodssetTotalStars() and getTotalStars().

Similar to static properties, static methods have a universal functionality. These methods can be called from any instance to update and return the value of starsInTheSky.

An interesting aspect about static methods (and properties) is that they can be accessed simply by referencing the class name, followed by the name of the method, such as:


Sky.setTotalStars(999999999); //One star died

var numStars:Number = Sky.getTotalStars();


In this example, we've used the class name (Sky) instead of an instance name to invoke both the setTotalStars() and getTotalStars() methods. This makes sense due to the class-wide functionality of static methods and properties. You've used similar syntax when invoking methods of the Math class, which has several static methods:


Math.round();

Math.random();

Math.floor();

Math.ceil();


and so on.

NOTE

A class method (static or not) can change the value of a static property, but a static method cannot change the value of an instance-based property.