Abstract classes are an explicit language feature of Java via the abstract keyword. In C++ they are less explicit via pure virtual functions. In AS3 they are only enforceable at runtime. There are many ways to go about creating abstract classes. This article shows you some of the ways.

The crux of the problem is that constructors must be public. Many ways of creating abstract classes rely on users of their classes to respect a parameter to the constructor. Consider this naive way:

class Abstract
{
	public function Abstract(abstract:String)
	{
		if (abstract != "i_should_not_be_instantiating_this_class_directly")
		{
			throw new Error("This class is abstract!");
		}
	}
}
class Subclass
{
	public function Subclass()
	{
		super("i_should_not_be_instantiating_this_class_directly");
	}
}

Here the user must pass a ridiculous string that insults them for using the class directly. This is wasteful as this string will be included in the SWF. A shorter string is not much better. It’s also a lot of typing for legitimate subclasses. It’s also a lot of CPU time spent comparing strings. Here is a better way to do it that I used until recently:

class Abstract
{
	protected static const ABSTRACT:Object = {};
 
	public function Abstract(abstract:Object)
	{
		if (abstract != ABSTRACT)
		{
			throw new Error("This class is abstract!");
		}
	}
}
class Subclass
{
	public function Subclass()
	{
		super(ABSTRACT);
	}
}

The prevalence of this way led to people around the office saying silly things like “did you pass ‘super abstract’?” Why should the user have to pass that object along? Well, this way requires (at run time) that the user pass the ABSTRACT object, which only the Abstract class and its subclasses have access to, thanks to the protected access specifier. Basically, we want to make the constructor protected, but language syntax forbids us. We get around this by making something else protected and requiring that to be passed.

I recently found out about a better way to do this. I have begun switching over code that used my old way to use the new way. Here it is:

class Abstract
{
	public function Abstract()
	{
		if (this["constructor"] == Abstract)
		{
			throw new Error("This class is abstract!");
		}
	}
}
class Subclass
{
	public function Subclass()
	{
		super(); // optional since no parameters are passed
	}
}

This way does not require a kludge Object to be present and passed, but instead directly checks the constructor field, which is set at run time, to see which class it is. For some reason, you can’t access this field with the dot operator, so you must index this to get it or do this:

Object(this).constructor;

Which way is cleaner is debatable. The only downside I see with this approach is that the class is not obviously abstract to its users. They may write or plan to write a good deal of code relying on the class being non-abstract only to have their plans ruined on the first run by the run time error. For this reason, I recommend properly naming your class with “Abstract” as a prefix. For example, “AbstractController” rather than “Controller” or “BaseController”. The latter two still seem non-abstract but the former clearly does not. Clarity is always important in programming.

I hope you’ll find this technique handy next time you go to make an abstract class.