Private constructors in ActionScript


#1

so Apache Royale post that

Private constructors in ActionScript

Apache Royale adds support for declaring the constructor of a class private instead of public in ActionScript. When a constructor is private, it cannot be instantiated with the new keyword outside of the class where it is defined. Private constructors are commonly used for implementing the singleton design pattern, which is when only one instance of a particular class should ever be created.

man I had this discussion so many times …


It is useless, you don’t need a new feature because you had that from day 1 with AS3.

I know I remember because I edited some wikipedia page long time ago about how to implement singletons in AS3 and some asshole editors decided to remove all my edit because … moronic ignorance?

anyway here we go

When I see this way to implement singletons (as described in the post above)

package
{
	public class Logger
	{
		private static var _instance:Logger;

		public static function getInstance():Logger
		{
			if(!_instance)
			{
				_instance = new Logger();
			}
			return _instance;
		}

		private function Logger()
		{
		}

		public function log(message:String):void
		{
			trace("LOG: " + message);
		}
	}
}

and then uh oh here how to access it

package com.example
{
	public class MyApplication
	{
		public function MyApplication()
		{
			Logger.getInstance().log("Application started");
		}
	}
}

I really want to take one of my shoes off and slap the guy senseless

or put another way: you absolutely don’t need to do that because it is AS3, not Java.

One of the great thing we have in AS3 is being able to declare definitions at the package level, and by definitions I mean not just classes, but everything like functions, variables and … constants!

And a singleton is not only some class that you can only instantiate once (eg. calling only once the new keyword), but is a unique pathway to that instance, eg. it has a unique global access point.

So if I want a singleton for logging stuff as a global access point I just need to declare a const
like this

package
{
    public const logger:Logger = new Logger();
}

It is a singleton because only one variable can occupy this special place named “logger”, nobody else can replace it or delete it, because it is a constant.

So above, it is the unnamed package, so yeah you will have access to logger everywhere, without even the need to import it.

Alternatively you could also declare in another place another singleton

package core.utils
{
    public const logger:Logger = new Logger();
}

there you would have to import it before being able to use it
eg. import core.utils.logger;

And … “oh what ??? but you instantiated it twice!!!”

Technically yes, there are two instances, but not a same place
one you access it through logger
the other one through core.utils::logger
not the same instance. not the same access point.

Now, if you absolutely need to instantiate it only once, while keeping a public constructor you can simply count.

eg.

package
{
	public class Logger
	{
		private static var _count:uint = 0;

		public function Logger()
		{
			if( _count == 1 )
			{
				Error.throwError( ArgumentError, 2012  /* kCantInstantiateError */, "Logger" );
			}

			_count++;
		}

		public function log(message:String):void
		{
			trace("LOG: " + message);
		}
	}
}

Now instead of the [Singleton pattern](http://Singleton pattern) Wikipedia definition (which is still insisting heavily on using getInstance())

I highly advise you to go read the C2 wiki Singleton pattern definition instead (web archive link because under remodelling)

Singleton Pattern

If a system only needs one instance of a class, and that instance needs to be accessible in many different parts of a system, you control both instantiation and access by making that class a singleton.

Often, a system only needs to create one instance of a class, and that instance will be accessed throughout the program. Examples would include objects needed for logging, communication, database access, etc. You could pass such an instance from method to method, or assign it to each object in the system. However, this adds a lot of unnecessary complexity.

Or, you could make that single instance the responsibility of the class, and then query the class for the instance. Therefore, let the class create and manage the single instance of itself, the Singleton. Wherever in the system you need access to this single instance, query the class.

Simply put,

Ensure a class has only one instance, and provide a global point of access to it.

Also on the subject go read the following

And many more very good materials on this blog.


Now about all that, I would need to add a little comment about Singletons (uppercase S) and singletons (lowercase s)

Yes singletons are bad and make code hard to test, but those are theSingletons (uppercase S), eg. singletons defined as global variables.

You could use singletons (lowercase s), unique instance of a class that you pass around so everyone reuse them, and if you need to test them you can then replace the instance with something else (a mock for example).

Let’s take a simple application that need to a configuration

you could declare a config Singleton, next to the Application class
eg.

package
{
    public const config:Configuration = new Configuration()

    public class Application
    {
        ///...
    }
}

and in many other packages/classes you can reuse this global variable config

or you could define config as property of Application and pass that unique property around

package
{
    public class Application
    {
        private var _config:Configuration;

        public function Application( config:Configuration = null )
        {
            if( !config )
            {
                _config = new Configuration();
            }        
        }

        public function get config():Configuration
        {
            return _config;
        }
    }
}

that’s your singleton (lowercase s), it is unique to your app, kind of global because you pass it around, but you can override it you need to (for testing, unit testing, etc.).

The way you pass it around is

// from within the Application class
// directly pass the Configuration instance from the class Application
new OtherClass( config )

// or
// directly pass the reference to the Application itself
new OtherClass( this )

If you just have one singleton like config yeah you can pass the instance directly,
but let’s say you have many singletons like that: layout, ui, network, etc.
passing the reference to the Application allow to pass only one param and have access to all the singletons as properties of this app.

Anyway, that’s already way too much text on singletons :smiley: