Flash CS3 Documentation |
|||
| Programming ActionScript 3.0 > ActionScript language and syntax > Packages and namespaces > Packages | |||
Packages in ActionScript 3.0 are implemented with namespaces, but are not synonymous with them. When you declare a package, you are implicitly creating a special type of namespace that is guaranteed to be known at compile time. Namespaces, when created explicitly, are not necessarily known at compile time.
The following example uses the package directive to create a simple package containing one class:
package samples
{
public class SampleCode
{
public var sampleGreeting:String;
public function sampleFunction()
{
trace(sampleGreeting + " from sampleFunction()");
}
}
}
The name of the class in this example is SampleCode. Because the class is inside the samples package, the compiler automatically qualifies the class name at compile time into its fully qualified name: samples.SampleCode. 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.
Many developers, especially those with Java programming backgrounds, may choose to place only classes at the top level of a package. ActionScript 3.0, however, supports not only classes at the top level of a package, but also variables, functions, and even statements. One advanced use of this feature is to define a namespace at the top level of a package so that it will be available to all classes in that package. Note, however, that only two access specifiers, public and internal, are allowed at the top level of a package. Unlike Java, which allows you to declare nested classes as private, ActionScript 3.0 supports neither nested nor private classes.
In many other ways, however, ActionScript 3.0 packages are similar to packages in the Java programming language. As you can see in the previous example, fully qualified package references are expressed using the dot operator (.), just as they are in Java. You can use packages to organize your code into an intuitive hierarchical structure for use by other programmers. This facilitates code sharing by allowing you to create your own package to share with others, and to use packages created by others in your code.
The use of packages also helps to ensure that the identifier names that you use are unique and do not conflict with other identifier names. In fact, some would argue that this is the primary benefit of packages. For example, two programmers who wish to share their code with each other may have each created a class called SampleCode. Without packages, this would create a name conflict, and the only resolution would be to rename one of the classes. With packages, however, the name conflict is easily avoided by placing one, or preferably both, of the classes in packages with unique names.
You can also include embedded dots in your package name to create nested packages. This allows you to create a hierarchical organization of packages. A good example of this is the flash.xml package provided by the Flash Player API. The flash.xml package is nested inside the flash package.
The flash.xml package contains the legacy XML parser that was used in previous versions of ActionScript. One reason that it now resides in the flash.xml package is that the name of the legacy XML class conflicts with the name of the new XML class that implements the XML for ECMAScript (E4X) specification functionality available in ActionScript 3.0.
Although moving the legacy XML class into a package is a good first step, most users of the legacy XML classes will import the flash.xml package, which will generate the same name conflict unless you remember to always use the fully qualified name of the legacy XML class (flash.xml.XML). To avoid this situation, the legacy XML class is now named XMLDocument, as the following example shows:
package flash.xml{class XMLDocument {}class XMLNode {}class XMLSocket {}}
Most of the Flash Player API is organized under the flash package. For example, the flash.display package contains the display list API, and the flash.events package contains the new event model.
ActionScript 3.0 provides significant flexibility in the way you organize your packages, classes, and source files. Previous versions of ActionScript allowed only one class per source file and required that the name of the source file match the name of the class. ActionScript 3.0 allows you to include multiple classes in one source file, but only one class in each file can be made available to code that is external to that file. In other words, only one class in each file can be declared inside a package declaration. You must declare any additional classes outside your package definition, which makes those classes invisible to code outside that source file. The name of the class declared inside the package definition must match the name of the source file.
ActionScript 3.0 also provides more flexibility in the way you declare packages. In previous versions of ActionScript, packages merely represented directories in which you placed source files, and you didn't declare packages with the package statement, but rather included the package name as part of the fully qualified class name in your class declaration. Although packages still represent directories in ActionScript 3.0, packages can contain more than just classes. In ActionScript 3.0, you use the package statement to declare a package, which means that you can also declare variables, functions, and namespaces at the top level of a package. You can even include executable statements at the top level of a package. If you do declare variables, functions, or namespaces at the top level of a package, the only attributes available at that level are public and internal, and only one package-level declaration per file can use the public attribute, whether that declaration is a class, variable, function, or namespace.
Packages are useful for organizing your code and for preventing name conflicts. You should not confuse the concept of packages with the unrelated concept of class inheritance. Two classes that reside in the same package will have a namespace in common, but are not necessarily related to each other in any other way. Likewise, a nested package may have no semantic relationship to its parent package.
If you want to use a class that is inside a package, you must import either the package or the specific class. This differs from ActionScript 2.0, where importing classes was optional.
For example, consider the SampleCode class example from earlier in this chapter. If the class resides in a package named samples, you must use one of the following import statements before using the SampleCode class:
import samples.*;
or
import samples.SampleCode;
In general, import statements should be as specific as possible. If you plan to use only the SampleCode class from the samples package, you should import only the SampleCode class rather than the entire package to which it belongs. Importing entire packages may lead to unexpected name conflicts.
You must also place the source code that defines the package or class within your classpath. The classpath is a user-defined list of local directory paths that determines where the compiler will search for imported packages and classes. The classpath is sometimes called the build path or source path.
After you have properly imported the class or package, you can use either the fully qualified name of the class (samples.SampleCode) or merely the class name by itself (SampleCode).
Fully qualified names are useful when identically named classes, methods, or properties result in ambiguous code, but can be difficult to manage if used for all identifiers. For example, the use of the fully qualified name results in verbose code when you instantiate a SampleCode class instance:
var mySample:samples.SampleCode = new samples.SampleCode();
As the levels of nested packages increase, the readability of your code decreases. In situations where you are confident that ambiguous identifiers will not be a problem, you can make your code easier to read by using simple identifiers. For example, instantiating a new instance of the SampleCode class is much less verbose if you use only the class identifier:
var mySample:SampleCode = new SampleCode();
If you attempt to use identifier names without first importing the appropriate package or class, the compiler will not be able to find the class definitions. On the other hand, if you do import a package or class, any attempt to define a name that conflicts with an imported name will generate an error.
When a package is created, the default access specifier for all members of that package is internal, which means that, by default, package members are only visible to other members of that package. If you want a class to be available to code outside the package, you must declare that class to be public. 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, you will generate an error, as the following example shows:
import samples.SampleCode; import samples.CodeFormatter; var mySample:SampleCode = new SampleCode(); // okay, public class var myFormatter:CodeFormatter = new CodeFormatter(); // error
If you want both classes to be available outside the package, you must declare both classes to be public. You cannot apply the public attribute to the package declaration.
Fully qualified names are useful for resolving name conflicts that may occur when using packages. Such a scenario may arise if you import two packages that define classes with the same identifier. For example, consider the following package, which also has a class named SampleCode:
package langref.samples
{
public class SampleCode {}
}
If you import both classes, as follows, you will have a name conflict when referring to the SampleCode class:
import samples.SampleCode; import langref.samples.SampleCode; var mySample:SampleCode = new SampleCode(); // name conflict
The compiler has no way of knowing which SampleCode class to use. To resolve this conflict, you must use the fully qualified name of each class, as follows:
var sample1:samples.SampleCode = new samples.SampleCode(); var sample2:langref.samples.SampleCode = new langref.samples.SampleCode();
|
NOTE |
|
Programmers with a C++ background often confuse the |
Flash CS3
RSS feed | Send me an e-mail when comments are added to this page | Comment Report
Current page: http://livedocs.adobe.com/flash/9.0/main/00000041.html
Comments
mgoodes said on Sep 29, 2007 at 7:35 PM :