9.1 Package Syntax

 <  Day Day Up  >  

Every package has a name that describes the classes it contains. By convention, package names do not use initial caps but might use mixed case, such as greatUtils . This helps distinguish them from classes, which by convention start with a capital letter. For example, a package that contains classes for a game might be named game , while a package that contains general utilities might be named tools , and a library of visual classes might be named graphics . Delaying, for a moment, the discussion of how to create a package, let's see how the classes within an existing package are accessed.

To refer to a specific class within a package, we use the dot operator, as follows :

   packagename   .   ClassName   

For example, in the following code, the names game , tools , and graphics are package names and the names Player , Randomizer , and Vector2D are class names:

 game.Player tools.Randomizer graphics.Vector2D 

Packages can be nested to form a hierarchy; that is, a package can contain another package. For example, the game package might contain a vehicles package that contains a SpaceShip class. When referring to a class in a nested package, separate each package name with the dot operator. For example:

 game.vehicles.SpaceShip 

By nesting packages, we can organize our classes into discrete subcategories within a larger category, which again prevents naming conflicts. For example, a traffic simulation application and a driving game may both want to use the vehicles namespace. To do so without naming conflicts, each application must nest vehicles within the larger application namespace:

 trafficsimulator.vehicles game.vehicles 

On a more general level, two companies may both want to use the game namespace for the creation of games . Namespaces, therefore, often include the name of the organization producing the classes they contain, as in:

 somecompany.game.vehicles 

As we'll learn later, under "Package Naming Conventions," many organizations use their domain name as a namespace, because it is guaranteed to be unique.

Flash's own v2 component classes are categorized in hierarchical packages. For example, the classes for general user interface components such as List, Button, RadioButton, and ComboBox are contained by the mx.controls package. Classes related to the individual List component are stored in a nested package, mx.controls.listclasses . And components that act as application containers, such as Window and ScrollPane, are stored in the mx.containers package. Notice that a package can contain both classes and other packages, much as a file folder can contain both files and other folders.

A reference to a class that includes its complete package name is known as a fully qualified reference . By contrast, an unqualified reference includes just the class name. For example, SpaceShip is an unqualified reference, while game.vehicles.SpaceShip is a fully qualified reference.

Prior to discussing packages, we've used unqualified references when creating instances of classes and specifying the datatypes of variables , parameters, and return types. For example, if the class SpaceShip were not in a package, we would use the following syntax to create a SpaceShip instance and store it in a typed variable:

 var ship:SpaceShip = new SpaceShip( ); 

However, if a class is in a package, we must use a fully qualified reference when creating instances of the class and specifying the datatypes of variables, parameters, and return types. Therefore, if the SpaceShip class were in the package game.vehicles , we would use fully qualified references, such as:

 var ship:game.vehicles.SpaceShip = new game.vehicles.SpaceShip( ); 

Similarly, when SpaceShip is not in a package, we specify the return type of a method using :SpaceShip , as in:

 public function getClosestShip ( ):SpaceShip {   // Method body not shown... } 

However, if the SpaceShip class is in a package, such as game.vehicles , we must declare the fully qualified path . So the preceding example becomes:

 public function getClosestShip ( ):game.vehicles.SpaceShip {   // Method body not shown... } 

We haven't talked yet about how to define the SpaceShip class or put it in the vehicles or game.vehicles package. Regardless, you'll notice that using fully qualified class references becomes tedious in a hurry. The following code requires more typing and takes longer to read than its nonpackage counterpart :

 var ship:game.vehicles.SpaceShip = new game.vehicles.SpaceShip( ); 

To make life easier, ActionScript 2.0 provides the import statement, covered next .

9.1.1 The import Statement

The import statement lets us use an unqualified class reference as an alias (shorthand) for a fully qualified class reference. The basic syntax of import is:

 import   packagename   .   ClassName   ; 

After the import statement appears in a script or class, every unqualified reference to ClassName is automatically converted to the fully qualified reference, packagename.ClassName . For example, after issuing the following import statement:

 import game.vehicles.SpaceShip; 

the compiler will subsequently treat the unqualified reference SpaceShip as though it were literally game.vehicles.SpaceShip .

Hence, the earlier assignment statement:

 var ship:game.vehicles.SpaceShip = new game.vehicles.SpaceShip( ); 

can be shortened to:

 import game.vehicles.SpaceShip; var ship:SpaceShip = new SpaceShip( ); 

Because of the import statement, the compiler knows we mean game.vehicles.SpaceShip when we specify the unqualified class name SpaceShip . The import statement doesn't allow us to specify an identifier to use in place of the fully qualified reference; the alias name is always the name of the class, excluding the package name(s). Don't try something like this (it won't work):

 import spaceAlias = game.vehicles.SpaceShip;  // Won't work! 

9.1.2 Importing an Entire Package

The earlier import statement:

 import game.vehicles.SpaceShip; 

imports only the SpaceShip class, not other classes in the package. To import all the classes in a package, use the wildcard character, *, as follows:

 import   packagename   .*; 

This wildcard syntax lets us refer to any class in packagename by its unqualified name rather than its fully qualified name (i.e., packagename . ClassName ).

For example, suppose the geometry package contains three classes Circle , Triangle , and Rectangle . Rather than importing each class individually, as follows:

 import geometry.Circle; import geometry.Triangle; import geometry.Rectangle; 

we can simply use:

 import geometry.*; 

After that statement has been issued, we can then refer to Circle , Triangle , and Rectangle , without including the package name, geometry .

If we use package wildcards to import two classes with the same name but from different packages, we again encounter a namespace collision. To access the ambiguous classes, we must use their fully qualified class names. For example, suppose we're writing an application that uses the classes game.vehicles.Ship and ordering.Ship . The application imports all classes in game.vehicles and in ordering :

 import game.vehicles.*; import ordering.*; 

When we attempt to access the Ship class without qualification, the class that was imported first ( game.vehicles.Ship ) is used:

 var s:Ship = new Ship( );  // Creates a new   game.vehicles.Ship   

The only way to create an ordering.Ship instance is to use a fully qualified reference, as in:

 var s:ordering.Ship = new ordering.Ship( ); 

To avoid confusion, we should use fully qualified names for all references to Ship . However, attempting to import two classes of the same name directly, as in:

 import game.vehicles.Ship; import ordering.Ship; 

yields this error:

 The class 'ordering.Ship' cannot be imported because its leaf name is already being resolved to imported class 'game.vehicles.Ship'. 

The solution is to not import either Ship class and use only fully qualified references to access game.vehicles.Ship and ordering.Ship .

Note that wildcard imports work with only one package at a time. There is no way to import an entire hierarchy of packages. We must import the classes of each package individually. For example, to import the classes in game.vehicles , game.logic , and game.data , we must use:

 import game.vehicles.*; import game.logic.*; import game.data.*; 

not:

 import game.*; 

The statement import game.* imports only the classes contained by the game package; it does not import any classes in subpackages of game .

Don't confuse the import statement with the #include directive! The two are completely unrelated. The #include directive copies external code into the current script, whereas import merely establishes an unqualified class name (e.g., SpaceShip ) as an alias for a fully qualified class name (e.g., game.vehicles.SpaceShip ). The import statement pertains only to classes stored in packages. Imported classes are compiled into a movie only if they are actually referenced in it. Included code, by contrast, is compiled into the movie whether it is needed or not, so be frugal with your #include directives.


9.1.3 Package Naming Conventions

Earlier we posed a scenario in which a game and a music component each defined unrelated classes named Player . We learned how packages could fix this problem by providing a unique, fully qualified identifier for each class. For example:

 musiccomponent.Player game.Player 

But this merely trades one problem for another. We still need a way to prevent one application's game.Player class from conflicting with another application's game.Player class. In other words, just as two class names can conflict, two package names can conflict. To avoid package or class naming conflicts you should use the convention of placing all your classes and packages in a package named after your organization's domain name. For example, classes and subpackages created by Acme Corp., whose domain name is acme.com , would be stored in the package:

 com.acme 

Notice that com precedes acme (the package name is the reverse of the domain name).

Thus, a game.Player class created by Acme and a game.Player class created by, say, Nintendo, could be stored safely in the following unique packages:

 com.acme.game.Player com.nintendo.game.Player 

Domain names are guaranteed to be unique by the system of authorized top-level-domain (TLD) registrars; thus, starting your package names with your organization's domain name avoids name conflicts with code developed by other organizations.

Naming conflicts remain a possibility within a large organization. So large organizations should adopt the convention of, say, including another identifier, such as the department name or project in the package hierarchy. Nintendo's GameCube division might use a package name such as:

 com.nintendo.gamecube.game.Player 

Notice that the first part of the package name, com.nintendo.gamecube , goes from the general ( com ) to the specific ( .nintendo and .gamecube ). Then the package name switches gears from the organization and department names to a name dependent on the purpose, in this case .game . Here are two more example package names from my own software, Unity. Unity is a multiuser application development kit, on top of which many different applications can be built. The following packages contain classes for the applications Tic Tac Toe and Avatar Chat:

 org.moock.unity.tictactoe org.moock.unity.avatarchat 

Notice that, again, both package names start with the general domain name ( org.moock ), then specify the general purpose ( .unity ), then specify the particular purpose (an application written for the Unity platform).

 <  Day Day Up  >  


Essential ActionScript 2.0
Essential ActionScript 2.0
ISBN: 0596006527
EAN: 2147483647
Year: 2004
Pages: 177
Authors: Colin Moock

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net