import newgrounds.util.AsMain;
Using OOP packages to organize and reuse your code
INTRODUCTION
This tutorial will cover an advanced OOP topic known as packages. Originally from the Java world, packages allow creating your own code repository, in other words, a collection of classes that can be reused in any of your projects for faster development.
PREREQUISITES
As: Basic Oop by Inglor
As: Oop Classes by Authorblues
As: Prototype, Proto and Inheritance by BleeBlap
ADDING A NEW CLASSPATH
Physically, packages are nothing more than a bunch of folders in a specific location. The path of this collection is known as the Classpath. By defaults, Flash is pointing to its own Classpath (defined as $(LocalData)/Classes), and to the folder of your .FLA file. You can add your own classpaths, and specify the order in which Flash looks them up.
By default, you would just create your classes in the same folder as your .FLA, which is fine and dandy until your class count starts to reach the dozens and your folder looks like a mess.
To modify the classpath settings, use the Edit Menu -> Preferences -> ActionScript Category -> "ActionScript 2.0 Settings..." button. [WARNING: if you delete the reference to $(LocalData)/Classes, your projects may not compile any longer]. Add a reference to one of your folders, for example, I keep my stuff in c:\flash\, so I've defined my custom classpath as c:\flash\classpath\ .
CREATING YOUR MASTER PACKAGE
Classpaths were designed to contain code from different people. Therefore it has become standard to place all your packages into a "master" package indicating the ownership of the package. Flash uses this for its own packages (e.g. flash.geom.Rectangle, flash.display.BitmapData). It's not a requirement, but will make things simpler if you ever use somebody else's code. Different master packages names will avoid conflicts.
I've called my master package 'newsdee', and it is contained in c:\flash\classpath\newsdee\. This way, if I create a "display" package, Flash will not get confused with its own "flash.display.*" package.
ASSIGNING CLASSES TO PACKAGES
Let's say that I want to add an utility class for arrays, ArrayUtils. I will save it in a sub-folder of my master package under the "util" category, i.e. c:\flash\classpath\newsdee\util\ArrayUtils
.as. After this, I should be able to use the command import as follows:
import newsdee.util.ArrayUtils;
But if you try to compile, Flash will complain that the class file does not match the package. This is because you need to specify what package the class belongs to in the file itself, like this:
class newsdee.util.ArrayUtil {
//example function
static author():String {
return "Newsdee";
}
//other class stuff
}
DEFINING SUB-PACKAGES
Sometimes, you will want to create classes that uses a large amount of subclasses. Instead of lumping them all in the same package, you can create a sub-package in the main category. For example, if I have a tile engine and bitmap generator, I could organize them as such:
newsdee.display.TileMap.as //tile engine master class
newsdee.display.tiles.GenericTile.as //TileMap subclass
newsdee.display.tiles.WalkableTile.as //TileMap subclass
newsdee.display.BitmapBuilder.as //bitmap maker class
newsdee.display.bitmaps.Transparent.as //BitmapBuilder subclass
newsdee.display.bitmaps.Perlin.as //BitmapBuilder subclass
Of course, how you organize your packages is completely up to you. Just be consistent so that you don't get confused later.
USING PACKAGE CLASSES
Once defined correctly, you can import and use classes in the same way that you use BitmapData and Rectangle. You will only need to specify the package name when importing the class at the first line of your script, and then you can just call the class by its own name:
import newsdee.util.ArrayUtils;
trace(ArrayUtils.getAuthor());
CAVEATS
- You can only import from the top down (i.e. you cannot import "../ParentFolderClass"), so you need to reference everything from the master package.
- Make sure to keep a package structure that makes sense, using sensitive short names. For example, I keep my utility classes under newsdee.utils.*;, my effects classes under newsdee.fx.*; etc.
- Using packages assumes weak dependency between classes of a different package. In other words, they work better if classes in each package can function without knowing about classes outside the package. Additionaly, a parent package will know about its sub-packages, but children packages should not need to know how the parent package works. This makes classes a bit harder to write, but guarantees that they are reusable in any context.
I hope this wasn't too confusing. Packages are a bit tricky and can be painful to debug. I've decided to write it as I've found no information around packages on NG, and I had some trouble with them initially. Hopefully this will help others in projects that have grown beyond several dozen of classes! Feel free to comment and let me know if some parts need clarification.