Abstract Static Variables

Abstract Static Variables

Problem

Current OO languages, including Java, won't allow a super-class, or an interface, to define a minimal set of class attributes that must be implemented by its sub-classes.

Context

You have completed the abstraction of objects into classes. You are in the process of abstracting common methods, algorithms and data structures into an abstract class. The code for one or more of the methods is identical and appears to be an excellent candidate for being abstracting to the new parent class. However, it relies on class constants. The type of the class constants is the same, but the actual value varies with each sub-class. The type of the class constant might not be a data primitive and subsequent sub-classes may also wish to over-ride the constant of the first generation sub-class.

Example

While developing a framework for persistent classes, you will need to create SQL statements to INSERT, UPDATE or SELECT class elements. If you have used the CrossingChasms pattern language, Memento and Proxy patterns, much of the actual code to do this is identical. The difference at runtime is the names of the database tables, the names of the database columns, the actual combination of tables necessary to restore the concrete objects state and the class name of the concrete object being restored. Having used the patterns mentioned above, the methods of the PersistentObject superclass simply become a series of Template Methods. However, each subclass needs to know its own table name, and column names. The subclass also needs a different set of relationships defined for retrieving, via foreign keys, references to other complex objects that are stored in the database. The code to manipulate these relationships is the same. Just their values are different.

Forces

Solution

  1. define one or more abstract, protected, data manipulators, which the sub-classes must over-ride in order to set the constants.
  2. define one or more abstract, protected, data inspectors, which the sub-classes must over-ride in order to get the constants.
  3. implement the common code using the Template Method pattern.
  4. Replace all references to the constants in the common code with the appropriate inspector.

  1. create references of the appropriate type to the constants.
  2. Over-ride the protected data manipulators.
  3. Instantiate the constants statically in each sub-class. In Java, this can be done using the static{} block of the sub-classes.

Resulting Context

There may be a runtime cost associated with the additional layer of indirection. However, this should not normally be the situation since using inspectors and manipulators is the preferred way to access variables. The added indirection involving both the super-class and the sub-classes will make the code more difficult to understand for programmers who are new to OO and to frameworks.

This pattern does not address class or static methods. -- ArickAnderson


This seems similar to (or a special case of?) SetterInjection as described in http://www.martinfowler.com/articles/injection.html


I think I get this, but some code examples in-line would help clarify it. Is this attempting to give you what "class instance variables" give you in Smalltalk? -- KyleBrown

I don't know Smalltalk, so I can't say. However, I have had some Smalltalk gurus tell me that they have used a similar technique. --ArickAnderson


I definitely need code examples here. I don't see how this pattern achieves what I think you are claiming - that all instances of a particular subclass will share a value, but instances of a different subclass will share a different value. Assuming that is what you want, there is a much simpler way:

in superclass:

	abstract protected int getClassConstant();

in subclass:

	protected int getClassConstant() { return 7; }

If this doesn't achieve your goals, can you explain why not, and how your pattern succeeds? -- RussellGold

Russel's approach is one technique for implementing the inspectors. His approach will work well as long as the class constants are primitives. If however, the class constants are a complex type, instantiating them each time you return them will incur the very performance/space cost that this pattern is trying to avoid. In light of y'alls feedback, I added the example section to the pattern. Does this clarify things sufficiently? -- ArickAnderson


Russell's technique doesn't force one to instantiate new objects. He is just suggesting the use of the TemplateMethod pattern to implement AbstractStaticVariables. The pattern can use "heavy-weight" objects by instantiating them as static variables and returning references to those objects. E.g:

in superclass:

	protected abstract Big_Object getClassConstant();

in subclass:
	private static Big_Object _class_const = ...
	protected Big_Object getClassConstant() { return _class_const; }

Obviously, to enforce a constant-like behaviour, the subclasses should ReturnImmutablesFromAccessorMethods that act as AbstractStaticVariables. -- NatPryce

This sounds a lot like KenAuer's SelfEncapsulation? pattern. -- MichaelFeathers


So, in this pattern, we have non-static methods that actually return static variables (constants, in fact).

Perhaps a complete, if contrived and deeply lame, example would help:

 abstract class AstronomicalObject?
 {

private Point3d position ;

private String name ;

// ...

protected abstract String getType() ;

public String toString() { return getType() + " \"" + name + "\" @ " + position ; }

}

class Star extends AstronomicalObject? {

// star-specific stuff here

protected String getType() { return "Star" ; }

}

A fleshing-out of the example above about accessing similar but differently-named database tables would be far better.

That's what we used to use in CeePlusPlus before RunTimeTypeInformation became a part of the language.


EditText of this page (last edited September 22, 2004)
FindPage by browsing or searching

This page mirrored in JavaIdioms as of April 29, 2006