Constructive Forces at Work

A constructor in Apex is called when an instance of a class is created. Code-wise constructors might look like member methods, but they differ in a couple of significant ways.

First, constructors can’t be called any other time than when creating an instance of a class, and second, constructors do not return values. Ever had the build error “Invalid constructor name: foo“? We soon learn that this actually means “Doh! You forgot to provide a return type for your method”.

This does mean, as it does in Java, that Apex constructors are not members that can be inherited:

A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.

http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

So, a subclass constructor can call a constructor of its superclass. Actually, constructors call superclass constructors automatically in Apex if we don’t do it explicitly. Try running this anonymous code block:

public class ClassOne {
    ClassOne() {
        system.debug('1');
    }
}
public class ClassTwo extends ClassOne {
    ClassTwo() {
        system.debug('2');
    }
}
public class ClassThree extends ClassTwo {
    ClassThree() {
        system.debug('3');
    }
}
ClassThree c = new ClassThree();

Note that class definitions in anonymous blocks are virtual by default, so we don’t need to supply the virtual modifier here.

And here’s a part of my debug log:

19:19:35.059 (59838092)|SYSTEM_CONSTRUCTOR_ENTRY|[16]|<init>()
19:19:35.059 (59944318)|SYSTEM_CONSTRUCTOR_ENTRY|[12]|<init>()
19:19:35.060 (60019420)|SYSTEM_CONSTRUCTOR_ENTRY|[7]|<init>()
19:19:35.062 (62725333)|USER_DEBUG|[3]|DEBUG|1
19:19:35.062 (62740937)|SYSTEM_CONSTRUCTOR_EXIT|[7]|<init>()
19:19:35.062 (62772600)|USER_DEBUG|[8]|DEBUG|2
19:19:35.062 (62780817)|SYSTEM_CONSTRUCTOR_EXIT|[12]|<init>()
19:19:35.062 (62807978)|USER_DEBUG|[13]|DEBUG|3
19:19:35.062 (62816118)|SYSTEM_CONSTRUCTOR_EXIT|[16]|<init>()

We have defined three classes where the second extends the first and the third extends the second. In each case we have defined a constructor, for debugging the order of execution, but we haven’t explicitly called a superclass constructor.

We find that each constructor implicitly invokes the superclass constructor before executing its own body. This works recursively until there are no more superclasses, so that the constructor method bodies are executed in order going down the inheritance chain from most-super-class to the actual class we are constructing.

We can influence the chaining behaviour to some degree by calling specific constructors with this and super.

If we have a class with several constructors, each with different arguments, we can delegate from one constructor to another of the same class using this(…), or select a particular constructor of a superclass using super(…):

public class ClassOne {
    ClassOne() {
        system.debug('1');
    }
}
public class ClassTwo extends ClassOne {
    ClassTwo() {
        system.debug('2');
    }
    ClassTwo(String value) {
        this();
        system.debug('2 ' + value);
    }
}
public class ClassThree extends ClassTwo {
    ClassThree() {
        system.debug('3');
    }
    ClassThree(String value) {
        super(value);
        system.debug('3 ' + value);
    }
}
ClassThree c = new ClassThree('foo');
19:39:29.054 (54167458)|SYSTEM_CONSTRUCTOR_ENTRY|[24]|<init>(String)
19:39:29.054 (54305037)|SYSTEM_CONSTRUCTOR_ENTRY|[20]|<init>(String)
19:39:29.054 (54384541)|SYSTEM_CONSTRUCTOR_ENTRY|[11]|<init>()
19:39:29.054 (54460886)|SYSTEM_CONSTRUCTOR_ENTRY|[7]|<init>()
19:39:29.057 (57619207)|USER_DEBUG|[3]|DEBUG|1
19:39:29.057 (57636883)|SYSTEM_CONSTRUCTOR_EXIT|[7]|<init>()
19:39:29.057 (57673115)|USER_DEBUG|[8]|DEBUG|2
19:39:29.057 (57684149)|SYSTEM_CONSTRUCTOR_EXIT|[11]|<init>()
19:39:29.057 (57743445)|USER_DEBUG|[12]|DEBUG|2 foo
19:39:29.057 (57766853)|SYSTEM_CONSTRUCTOR_EXIT|[20]|<init>(String)
19:39:29.057 (57829601)|USER_DEBUG|[21]|DEBUG|3 foo
19:39:29.057 (57848548)|SYSTEM_CONSTRUCTOR_EXIT|[24]|<init>(String)

It is important to note that in order to preserve the order of execution of the chain of constructors, super or this must be the first line of the body of a constructor.

Constructors however are optional, and so to preserve the constructor chain, the compiler will provide a default zero-argument constructor for us just as long as we don’t provide any constructors ourselves:

If you write a constructor that takes arguments, you can then use that constructor to create an object using those arguments. If you create a constructor that takes arguments, and you still want to use a no-argument constructor, you must include one in your code. Once you create a constructor for a class, you no longer have access to the default, no-argument public constructor. You must create your own.

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_constructors.htm

Which also means of course that if you do create a constructor in an abstract/virtual class that takes argument(s), you must then also provide a zero-argument constructor in order to extend the class, even if you don’t need one (it has an empty body). If you don’t then you will get a build error when you extend the class:

Parent class has no 0-argument constructor for implicit construction

Links

http://salesforce.stackexchange.com/questions/24275/inheriting-non-implicit-constructors-on-apex-classes

Force.com Apex Code Developer’s Guide – Using Constructors

This entry was posted in Documentation and tagged . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s