I see your privates: How objects of the same class can share private variables in AS3

Today, I was surprised to discover something that I didn’t know about private variables in AS3. If an instance of class A has a reference to another instance of class A, then the second object’s private variables are accessible to the first object. No restrictions. No special tricks. You just use obj.variableName like any other property request. I’ll show you some example code, and you can try it yourself.

First, let’s set up the situation. Alice has a secret in her diary. Trudy wants to know Alice’s secret, so she’s going to sneak in and take a peek. Here’s a simple document class that presents our story in code:

package
{
	import flash.display.Sprite;

	public class ISeeYourPrivates extends Sprite
	{
		public function ISeeYourPrivates()
		{
			//the intruder
			var trudy:Person = new Person("Trudy");

			//the victim
			var alice:Person = new Person("Alice", "I kissed a girl, and I liked it!");

			//Trudy is curious, and she wants to read Alice's diary
			trudy.peekIntoDiary(alice);
		}
	}
}

Finally, this UML-like diagram below also shows what’s happening:

UML-like diagram. Alice and Trudy are instances of Person. Through peekIntoDiary(), Trudy can access Alice's private variable _secret.

Next, let’s look at the Person class and see how the peekIntoDiary() method works:

package
{
	public class Person
	{
		public function Person(name:String, secret:String = null)
		{
			this.name = name;
			this._secret = secret;
		}

		public function peekIntoDiary(target:Person):void
		{
			trace(this.name, "is looking at ", target.name + "'s secret:", "\"" + target._secret + "\"");
		}

		public var name:String;
		private var _secret:String;
	}
}

As you can see the secret value sent to the constructor gets stored in the private variable _secret. Another Person instance is passed to the peekIntoDiary() method. In this case, the Trudy object (this) now has access to the Alice object (target). The trace() output reads:

Trudy is looking at Alice’s secret: “I kissed a girl, and I liked it!”

Yes, Alice’s private variable _secret has just been accessed by Trudy. Bet you didn’t expect that to work. I know I didn’t. Don’t believe me? Try it yourself. The code above compiles and runs.

It makes some sense if you consider that the private access modifier is actually a namespace. Basically, behind the scenes, the compiler automatically creates a separate namespace for each individual class that it names private. This private namespace is only accessible to the one class for which it is defined. That’s why other classes and subclasses can’t access private variables. However, due to the scope of the namespace, all instances of the same class can access the private members of other instances. To be truly private, each individual instance of a class would needs its own namespace that other instances wouldn’t know about. I’m not even sure if that’s possible, but I have a vague idea of how it might work.

Does it matter? No, not really. You’ll rarely find yourself in an situation where this behavior can be useful (see the credited link below for one possibility). I can’t think of a case where this can be considered a security risk either. It’s not much different than using object["variableName"] to get at private variables in AS2. Mainly, I wanted to share because it’s somewhat unexpected behavior.

Credit: Thanks to Nick Bilyk for pointing this out in a post about cloning objects.

About Josh Tynjala

Josh Tynjala is a frontend developer, open source contributor, bowler hat enthusiast, and karaoke addict. You might be familiar with his project, Feathers UI, an open source user interface library for Starling Framework that is included in the Adobe Gaming SDK.

Discussion

  1. Daniel R.

    I wouldn’t say that the behavior is unexpected. As you pointed out private is just another namespace, just one that the compiler has special treatment for. The documentation about access control namespace attributes defines private as “makes a property visible only to callers within the property’s defining class.” The example you have above shows how the peekIntoDiary() function since it is defined in the Person class can access anything defined else defined in the Person class, regardless of the instance.

  2. Daniel

    Hello Josh,

    Nice post. I am taking a class called «Concepts of Object-Oriented Programming.» There I found out about this behavior in Java, meaning «private» is class-private, not object-private. I was telling my friend that there’s no way this works the same in ActionScript. I guess I was wrong after all. =)

    Cheers,
    Daniel

  3. Josh Tynjala

    Thanks to the two Daniels for the interesting info. I guess I always just assumed that, using the terms the second Daniel mentioned, private means object-private rather than class-private. Like I said, it makes sense from a namespace point-of-view, but this is an assumption I’ve been making since my CS101 class in college (when I was using Java, which I’ve now learned has the same behavior). From my point of view, making private mean class-private rather than object-private makes objects less encapsulated, so I guess that’s why I made the assumption.

    Anyway, interesting stuff. I’m sure this knowledge will come in handy at some point in the future.

  4. Olivier Allouch

    Actually, this behavior is completely standard and logical. Who decided this variable is private ? The guy that wrote that class. When he writes other methods of this class, he is home. If he can make this variable public, why couldn’t he read it when it’s private ? It’s his !

  5. Olivier Allouch

    And to be completely honest, I have to say I also was surprise when I first discovered it 🙂
    The OOP makes us see objects as independent individuals, and we tend to forget that OOP security is to protect from coders, not objects.
    We’re just getting too virtual, I guess.

  6. Josh Tynjala

    I have a question for the commenters who say this isn’t unexpected. If it seems logical to you, then why don’t I see developers taking advantage of this behavior more often? From the moment I started learning software development in 2001 to yesterday, over seven years later, I’d never seen anyone use this feature. Why not? Are there too few use-cases? Is it rare for one instance to have a reference to another instance of the same type? What is it?

    It honestly seems very strange to me that I would never have encountered this in code written in any of the languages I’ve used before, whether ActionScript, Java, or something else. I’ve probably seen every other obscure feature of ActionScript used at least once. I’ve even seen undocumented features in AS2 used sometimes. Why not this one?

  7. Mike Welsh

    This behavior is pretty standard across langauges, but it’s definitely a surprise the first time you notice it. I know C++ and Java operate the same way. As others have pointed out, it makes sense and can be useful.

    Another case would be for a tree or linked-list object, where you may have code to remove a node from the tree: _parent._child = null; _parent = null;

    You don’t see it too often, but it’s definitely out there. Maybe people are just so accustomed to making public accessor methods for their private variables, that they end up using them even in these cases? 🙂

  8. Olivier Allouch

    The tree structure is an excellent example.
    And, you may not have noticed it because it’s sometime not simple to notice it, especially in Java where you don’t have the get/set types of functions, so no need for “_” before object arguments.

  9. Darren

    Josh, maybe the question is really what use-cases can you think of where this would be useful? The point of private variables is not to stop bad objects seeing/changing something they shouldn’t, it’s to stop bad coders seeing/changing something they shouldn’t. As Olivier alluded to above, if you have access to the class to put in your peekIntoDiary function, you could just as easily put in a getter function or make the variable public.

  10. Matt

    The place I see this used most in Java is in implementing a .equals() method. Usually classes which provide their own .equals method will just go through and compare all the member properties of two instances. It would be awkward to implement without access to the other object’s private members.

    That being said, I agree with the general sentiment that the behavior is non-obvious at first.

  11. Paul

    A private member variable may be accessed if a method is written for it, but it can not be accessed if no method exists for it. In other words:

    var oJane:Person = new Person(‘Jane’, ‘Jane has a secret’);

    // will error:
    // trace(‘Jane is secure from direct member access: ‘ + oJane._secret);

    // will succeed:
    trace(‘Jane is not secure by method and design: ‘ + oJane.peekIntoDiary(this));