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
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
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
Perhaps a complete, if contrived and deeply lame, example would help:
abstract class AstronomicalObject? {A fleshing-out of the example above about accessing similar but differently-named database tables would be far better.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" ; }
}
That's what we used to use in CeePlusPlus before RunTimeTypeInformation became a part of the language.
This page mirrored in JavaIdioms as of April 29, 2006