Packages and AS3 v. AS2 access modifiers introduced

AS2 access modifiers were simple to understand. Each class was like a cohesive object with an outside and an inside. If a property could be accessed from the outside, it was public. If it was used for the inner workings of the class, it was private.

private

AS3 presents a considerably more jagged picture. Senocular has laid out the new landscape with characteristic economy and astringency in these posts, but I had to read them about five times before I understood them.

The most striking innovation is the new default access modifier, internal. The first question about this modifier is: internal to what?

The answer is a package, which is basically a folder of related class files. Here is the “family” package:

pic-41.jpg

In each class file, there is a package address:

package family {
class father {
public function father () {
}
}
}

Keep in mind that this is not a package declaration, just a partial address. The package is the containing folder, and each class file within the package has the same address:

//different class file, same package address
package family {
class son extends father {
public function son () {
}
}
}

It took me longer than I’d like to admit to get this. I kept thinking that each file was itself a package, which I found painfully odd, because each file can only have one public class. How could a package have just one class?

Once I was enlightened, the internal access modifier made perfect sense. A class in a package has the right to access internal properties and methods of any other class in that package.

pic-51.jpg

Using the internal keyword saves you from writing getters: getDarkFamilySecret(), getObviousInsecurities(), and makes explicit what properties are relevant on the package level.

The other reason I had to read Senocular five times was that I was thinking packages were constructs to group similar files to help organize the importation of classes. This is technically true, but misleading. A package folder is less a shelf in a class library and more a project file with lots of files that actually work together.

The internal access modifier is helpful in a package folder in which at least one class instantiates, composes and references a bunch of other classes, a folder like this:

[Family.as, Father.as, Son.as, Daughter.as, Parent.as] or [Carpenter.as, Hammer.as, Nail.as, Plank.as].

Internal would be less helpful in packages like these:

[Hammer.as, SledgeHammer.as, PonyHammer.as] or [Hammer.as, Screwdriver.as, Saw.as].

The rest of the new access modifiers break up the old model along a different vector. While the internal access modifier allows you to pry open the old-style clam-like object and expose whatever you choose to its package mates, the new protected and private allow you to modulate any classes’ level of exposure in the chain of inheritance.

pic-21.jpg

The new private is very, very private. Private properties and methods stay by their class, always and exclusively:

pict-91.jpg

The new protected, on the other hand, is like the old private. Protected properties can’t be accessed externally, but they show up in subclasses.

pic-71.jpg

Private and protected give us fine-grained control over how a class exposes its various elements to its subclasses and superclass:

1. If I want a properties of a class to be both public and defined for generations below, I make them public. Public properties are the same in AS2 and AS3: accessible to anyone, and passed down from one generation to the next.

2. If I want properties to be both hidden and defined for generations below, I make them protected. Public and protected both provide explicit defaults for properties, allow subclasses to polymorphically override them.

3. If I want properties to be defined without reference to generations above or below, I make them private. The exact same private property declared in a subclass does not need to be overriden, because it’s not even seen by the subclass. A private property is the ultimate one-off.

What’s most confusing about the new system is that the public-private distinction does double duty, covering both the relationship between classes related through inheritance, and the relationship of classes trying to access each other. I’m curious to know if other languages break out this distinction with extra modifiers.

pic-1.jpg

Notice the missing square here–what about a publicly accessible property that is generationally one-off? Would that even be useful?

9 comments.

  1. Hi
    Thank you very much. It’s very useful for me

    :)

    Good Luck

  2. A public accessible one-off method can be achieved by using final -
    ie. public final function accessibleButNotBySubclassOverrides()

    why it might be useful, is up for debate- but i could see some directive that an abstract class would have that is meant to call certain overrides through a non-overiddable public method.

    -todd

  3. Thanks Todd, for that solution.

    I had thought using final meant you could not override a method. Now I realize that you cannot inherit it, either. So your method declaration might also be:

    public final function accessibleHereButNotInAnySubclassPeriod()

  4. Thank you for your entertaining pictures. I’m still trying to grasp the concept, but i should get it soon.

    Question though, would the internal still apply even if Son wasn’t a extend of Father?If it was an extend, wouldn’t you just use Super to reference the superclass?

  5. Dazzer:

    Internal DOES apply even if father is not the superclass of son.

    Internal access is access to a property granted by one object to another object when BOTH OBJECTS HAVE CLASS FILES IN THE SAME FOLDER/PACKAGE. It does not matter if they are related through inheritance.

    Say there are two class files in a folder name Family, Father.as and Son.as. Here’s the son:

    package Family {
    public class Son {
    internal var favoriteDrug:String
    public function Son() {
    favoriteDrug=”alcohol”
    }
    }
    }

    Here’s the father. He includes his son, Trinity-style:

    package Family {
    import Son;
    public class Father {
    protected var son:Son
    public function Father() {
    son=new Son
    }
    protected function snoop():String
    {
    return son.favoriteDrug;
    }
    }

    The father has access to the son’s favoriteDrug property simply because 1) his class file is in the same folder as the son’s class file and 2) because the son’s favoriteDrug property has the “internal” access modifier.

    No inheritance necessary.

    But if there IS inheritance, that does not mean the son can access all of the properties of the father anymore.

    Say the father class has a private “secret” property:

    private var secret:String=”alcohol”

    Say the son has his own snoop function:

    protected function snoop():String
    {
    //does not work!
    trace (super.secret);
    }

    Private properties do not get inherited, and can’t be accessed by subclasses.

    That’s a pretty big difference between AS2 and AS3. And it is confusing, because sometimes the same access modifiers are referring to objects that access each other, and sometimes to classes that access each other in the inheritance chain.

  6. I think i get it now.

    Thank you very much

  7. Pet,

    Check out namespaces- another way to restrict access to a method. They allow for related classes in different packages to call otherwise-private methods.

    The only problem is that I don’t think there are any security restrictions to importing and using a namespace. In other words, if you made a secret method:

    cousin_namespace function doStuff () :void;

    that is to be used by “cousin” classes (maybe those in a package below the main package, but that don’t inherit directly), there is nothing to prevent some arbitrary class from importing the “cousin_namespace” namespace and using it to call doStuff().

  8. [...] An application file with a mediator object should type all its component properties as internal. That way, if the mediator class is in the same package as the application class, it can access these components without asking for them. The mediator is by definition quite intimate with the application. (For more on the internal access modifier, see this post.) [...]

  9. Thanks for the analogies, definitely helpful for as3 n()()bs like me trying to visualize this new, more OO inheritance…

    Should you include all functions in packages?

    If you have general functions like displayLoadStats() for example that load library assets in different parts of an app for general purpose, is it bad form to just plop those functions into the actions window without it being in a class/package?

Post a comment.