Friday, 5 October 2007

Semi private constructors

There are times when you need access to a constructor for one specific purpose, but the constructor is not and should not be public.

To me these times are usually around unit testing when I want to manipulate my data structures into a testable state. Let me show you an example:

I have an object which reads its configuration from the classpath and now I want to test it. To do this I would have to create multiple configuration files (For all my options) and find a way to substitute the files between tests.

Now, for reasons dear to me, I keep unit tests out of the package itself into its own package. That means that the tests are really only allowed to do the same as everybody else, except I would prefer a constructor which took a java.util.Properties object directly rather than loading from the classpath, however, it is not for anybody else to use.

So much for an explanation, here's the solution....

Make the public constructor as usual, but create one protected constructor for special purposes, such as:

public class ConfigurationObject {
public ConfigurationObject() { this(loadPropertiesFromClassPath()); }
protected CoonfigurationObject(Properties props) {...}
}

Now in your unit tests, you can use the protected constructor from a public scope:

testOneConfiguration() {
ConfigurationObject co = new ConfigurationObject(prop1) {};
...
}
testTwoConfiguration() {
ConfigurationObject co = new ConfigurationObject(prop2) {};
}

Notice the curly braces after the constructor. This is merely a cunning way to use inner anonymous classes rather than any magic.

You can instantiate parent constructors in inner anonymous classes just by specifying the argument directly.

What do you think?

Of course this is a circumvention of access control, but for some situations I find it feasible. However, I prefer not to let it drift into the real architecture. What do you think?

0 comments:

Post a Comment