Private, public, and inner methods -> using namespaces

Say I have class Dog in package A.B.C and another class Cat in package A.B.C.D . There’s a mathod in Cat that I want to access from Dog, but without making that variable public. Is there a way to do that?

This one is a little complicated. Normally, members that need to be accessible between different classes and only those classes (i.e. not public) would be internal. This requires that the classes be in the same package, though. If not in the same package, public is the only default access attribute that will work.

The alternative? Define the members in a custom namespace (as TheCanadian pointed out). Namespaces for classes are just like namespaces for XML if you’re familiar with them. They basically provide a long, unique naming path that is used for a definition to help prevent naming collisions. In fact public, private, etc. and even packages are kinds of namespaces.

When defining class members in a namespace, the namespace replaces the access control attribute. So instead of using public or private, etc. you would use your namespace. Now, the problem with namespaces is that they are not 100% secure. In other words, there is no sure way to have “private” members in a namespace since anyone could technically recreate your namespace themselves if they knew the namespace url. However, if you keep that uri hidden, chances are people won’t have much of a chance of figuring it out. And really, in terms of member access, this is not a big deal. If people really wanted to access these properties, they’d hack into your source and change them to public. So really, don’t worry about that too much. It’s mostly a non-issue but something I thought worth mentioning (and I’ll show an example of what I mean by it).

So, a first introduction to class member namespaces. I would say that should probably start with a pre-defined namespace such as flash_proxy. This is a namespace defined for ActionScript to be used with the Proxy class. So go here:


And scroll down the index list until you see Proxy Class and take a look at those posts. They should (hopefully) get your feet wet since it shows a practical application of using namespaces for member access. This particular approach makes those members publicly accessible (since the flash_proxy namespace is public) but its a good place to start nonetheless.

And actually, that thread has a couple more examples of namespace usage in general, so check them out. I’ll also post an example in the context of your question below…

Ok, here’s an example using Cat and Dog. I switched the packages around since I figured it made more sense to put Cat in C and Dog in D ;). Basically the API consists of 3 methods, 1 public method for each the Cat and Dog classes, and an additional method in the Cat class that is defined in a custom namespace. This namespace is defined with the namespace keyword (which you can think of as being like ‘function’, ‘var’ or ‘const’ only for defining namespaces) privately in each of those classes. Why each? Because even though Cat is the only class that defines anything with that namespace, dog still needs to be able to access it using the namespace in which it was defined. Here are the classes:

// A/B/C/Cat.as
package A.B.C {
	
	public class Cat {
		
		private namespace animals = "usually/a/uri/but/can/be/anything";
		private var scaredy:int = 0;
		
		animals function intimidate(intimidation:int):void {
			scaredy += intimidation;
		}
		
		public function checkBackHair():void {
			trace("Back hair raised by a factor of "+scaredy);
		}
	}
}

You’ll notice the namespace definition as well as a private property called scaredy. This determines how scared the cat is at anytime. The public method for determining this is checkBackHair(), which conveniently relates directly to the scaredy property. In addition there is the intimidate() method. This is the method that is defined within a namespace. By using a namespace, it has no other access control. The namespace itself is the access control, though for all events and purposes it is essentially public, now just with a really long name. That’s all namespaces are in the end, prefixes to be given to names making them really long. By making them long, they become more likely to be unique. If you keep your namespace prefix hidden from the world, members defined in that namespace essentially become private.

Dog class:

// A/B/C/D/Dog.as
package A.B.C.D {
	
	import A.B.C.Cat;
	
	public class Dog {
		
		private namespace animals = "usually/a/uri/but/can/be/anything";
		
		public function introduce(cat:Cat):void {
			cat.animals::intimidate(10);
		}
	}
}

This one is a little simpler; one API for introducing the dog to a cat. The dog uses the Cat’s initimidate method to make the cat scared. In order to be able to use this method, it has to know how that method is defined, i.e. in what namespace, hence the namespace definition using the same uri value used in Cat. To call the method, the name qualifier operator ( :: ) is used as a prefix to the class member defined in that namespace. Basically what this is doing is taking the value of animals and prefixing it to the member name intimidate to give the cat reference a full path to the actual whole method name that, since defined in the animals namespace includes not just the term initimidate but also the namespace path. So in the end, you’re pretty much really calling something more like:

cat.usually/a/uri/but/can/be/anything/intimidate(10);

So lets put this in the context of a naive pet owner:

import A.B.C.Cat;
import A.B.C.D.Dog;

// new cat, easy life
var cindy:Cat = new Cat();
cindy.checkBackHair();
// Output: Back hair raised by a factor of 0

// getting a dog; good idea?
var butch:Dog = new Dog();
butch.introduce(cindy);
cindy.checkBackHair();
// Output: Back hair raised by a factor of 10

At first, everything is fine with a nice, relaxed kitty cat. But then comes the dog, and once introduced, we now have a scaredy cat. How did cindy become so scared? Because butch was able to intimidate her using a method in a namespace in which only cindy and butch (and presumably other animals) are familiar. The pet owner could try and take away some of this intimidation but they don’t know how.

cindy.intimidate(-10); // Error: inaccessible method

Even if they knew they needed a namespace, would they know which to use?

namespace animals = "idontknowwhat";
cindy.animals::intimidate(-10); // Error: inaccessible method

Generally there’s nothing to be done. That is unless the ower is a cat whisperer and was able to figure out the namespace. And this is where namespaces aren’t 100% private. Even in a closed system where source code is not available, private variables will always remain private, however, there’s always a chance that a namespaced variable could be accessed if someone was able to figure out the uri of the namespace used.

namespace ifigureditout = "usually/a/uri/but/can/be/anything";
cindy.ifigureditout::intimidate(-10);
cindy.checkBackHair();
// Output: Back hair raised by a factor of 0

And maybe you’re thinking, well, what’s the likelyhood of that REALLY happening? Actually, if people are looking, very. Why? Because describeType will tell you :beam:

So are namespaces a replacement for private? No. But they can help maintain a separation of class members that make it a little more difficult for them to be used in places other than those that have a fine understanding of the namespace being used. Usually, that’s good enough. :wink:

bookmarked, awesome reply :slight_smile:

thanks

He mentioned my name once in there so I’m happy :love:

Excellent post! :sen:

OMG. What have I done!

Thanks so much senocular!!!