ActionScript 3 fundamentals: Packages


 

Requirements
   
Prerequisite knowledge Required products  
You need to be familiar with variables,
functions, and objects in ActionScript 3.

 

User level
Beginning
Flash Builder (Download trial)
 
 
Most software projects contain many classes. Sometimes a project contains hundreds, if not thousands, of classes. Organizing those classes into related groups is standard practice and helpful. You use packages to organize your classes into related groups. The compiler also uses packages to define the full name for the classes they contain and to add a level of access control. In this article you will learn what a package is, how to create one, and how to import code within packages. You will also learn how packages are related to access control, help organize your code, and are part of creating fully qualified, unique names.

Creating packages

You use the package statement to declare a package in ActionScript 3. In the following example, the samples package is declared. It contains the class SampleCode.

 

package samples {
public class SampleCode {
public function SampleCode() {
}
}
}

In ActionScript 3 files, only one public class can be contained in the package block. The name of the file and the name of the class are the same. The file path corresponds to the package. The example code directly above would exist in a file named SampleCode.as which is in a package named samples.
 
You can also declare variables, functions, or namespaces at the top level of a package. Two limitations exist if you choose to make package declarations. First, the only access control attributes available at that level are public and internal. Second, only one package-level declaration per file can use the public attribute, whether that declaration is a class, variable, function, or namespace. The name of the file must match the name of the one public item.

Importing packages

 
To use a class that is inside a package, import either the entire package or the specific class using an import statement. The import statement tells the computer where to find the class definitions. If you try to use a class without importing it, an error results. Consider the SampleCode class example from above. The class resides in a package named samples. Use the following import statement to import the SampleCode class:
 
import samples.SampleCode;
 
Place the import statements inside the package block but outside the class block.
 
package { import samples.SampleCode; import samples.SampleShape; public class ExampleClass { public var mySample:SampleCode = new Sample Code(); public var myShape:SampeShape = new Sample Shape(); public function ExampleClass(){ } } }

 

Use the wildcard operator (*) to import all of the classes in a particular package:

 

package { import samples.*; public class ExampleClass { public function ExampleClass(){ var mySample:SampleCode = new Sample Code(); var myShape:SampeShape = new Sample Shape(); } } }
Note: Imported classes are not automatically included in your compiled SWF file. Only classes that are used in executable code are compiled and included. Your compiled SWF file does not include classes that have been imported but not used.
 
Programmers with a C++ background often confuse the import statement with #include. The #include directive is necessary in C++ because C++ compilers process one file at a time and don't look in other files for class definitions unless a header file is explicitly included. ActionScript 3 has an include directive, but it is not designed to import classes and packages. To import classes or packages in ActionScript 3, use the import statement and place the source file that contains the package in the class path.

Access control

 

You control where your code is available by using access control attributes when declaring variables and defining functions. You control where classes are available by using access control attributes with packages.
 
When a package is created, internal is the default access control attribute keyword applied to all members of that package. internal package members are only visible to other members of that package. Use the public access control attribute keyword to make package members available outside the package. For example, the following package contains two classes, SampleCode and CodeFormatter:
 
// SampleCode.as file package samples{ public class SampleCode {} } // CodeFormatter.as file package samples { class CodeFormatter {} }
 
The SampleCode class is visible outside the package because it is declared as a public class. The CodeFormatter class, however, is visible only within the samples package itself. If you attempt to access the CodeFormatter class outside the samples package, an error results, as the following example shows:
 
package examples{ import samples.SampleCode; import samples.CodeFormatter; public class UsingPackages { var mySample:SampleCode = new SampleCode(); // okay, public class var myFormatter:CodeFormatter = new CodeFormatter(); // error public function UsingPackages(){ } } }

Organization and hierarchy

 

Organize your classes into related groups. If you are building an application that draws, performs special calculations, and uses custom user interface components, place all of your drawing classes in a draw package, your calculations classes into a calculations package, and your user interface component classes in a ui package.
 
You can also include embedded dots (dot syntax) in your package name to create nested packages. Dot syntax allows you to create a hierarchical organization of packages. A good example of this practice is the flash.display package provided by ActionScript 3. The display package is nested inside the flash package.
 
The organization and hierarchy you create in code is also visible in your file system. Your class files exist in folders with the same names and nested structure as your packages.

Fully qualified names and uniqueness

 
Each class has a class name and a fully qualified name. The class name is the name defined in the class statement. The compiler creates the fully qualified name at compile time. The fully qualified name combines the package name with the class name using dot syntax. In the following example, the name of the package is samples. The name of the class is SampleCode. Because the class is inside the samples package, the fully qualified name of the class is samples.SampleCode.
 
package samples { public class SampleCode { public var sampleGreeting:String; public function SampleCode() { } public function sampleFunction() { trace(sampleGreeting + " from sampleFunction()"); } } }
The compiler also qualifies the names of any properties or methods, so that sampleGreeting and sampleFunction() become samples.SampleCode.sampleGreeting and samples.SampleCode.sampleFunction(), respectively.
 
Fully qualified names resolve name conflicts that could occur when using libraries, frameworks, or code written by multiple developers. Multiple classes with the same class name are not uncommon when code is shared. Without packages, the compiler does not know which class to use. If each of those classes is in a different package, the fully qualified name for each class is unique. The naming conflict is avoided. In the previous example code, the class SampleCode was created inside the samples package. In the example code below,a SampleCode class is created inside the langref package:
 
package langref { public class SampleCode {} }

 

Use the fully qualified names of both SampleCode classes to avoid a name conflict:
 
package { import samples.SampleCode; import langref.SampleCode; public class TestApplication { var firstExampleVar:samples.SampleCode = new samples.SampleCode(); var secondExampleVar:langref.SampleCode = new langref.SampleCode(); public function TestApplication(){ } } }

 

To further avoid naming conflicts when using shared code, use unique names for packages. Developers often place packages in a structure that uses a reversed domain name for the naming scheme. Domain names are unique so using them as part of the package naming scheme guarantees packages names are unique. For example, if you were deploying your application to http://www.example.com, you would create a com package that contained an example package that contained all other packages. The SampleCode class in the samples packages in the example above now has a fully qualified name of com.example.samples.SampleCode:

 

com.example.samples.SampleCode: package com.example.samples { public class SampleCode { public var sampleGreeting:String; public function SampleCode() { } public function sampleFunction() { trace(sampleGreeting + " from sampleFunction()"); } } }

Where to go from here

 
As an application grows, the chance of having two classes with the same name increases constantly. When applications are developed by multiple developers, multiple teams or over a long period of time, this chance increases dramatically.
 
Well named packages allow developers to avoid name conflicts and provide an extra measure of clarity about the intended use of a class. In ActionScript package names are another type of namespace and can be used with defined Namespaces, Objects and functions to make larger applications more manageable. To learn more about each of these topics, read ActionScript 3 fundamentals: Functions, ActionScript 3 fundamentals: Namespaces, Introduction to objects, Introduction to Classes, and Writing classes in ActionScript 3 (all coming October 31).

Acknowledgement

 
The content in this article is based on material originally published in the Learning ActionScript 3 user guide created by Adobe Community Help and Learning.

Acknowledgement

The content in this article is based on material originally published in the Learning ActionScript 3 user guide created by Adobe Community Help and Learning.