Most of the central classes of jME require one to branch the code just for
basic modifications. IMO, this conflicts with the stated goals and touted
advantages of jME. Basically, any class that I want to modify, I have to
duplicate huge chunks of original code or (what is more practical in this
situation-- replace the jME class with my own copy), since it is impossible for
subclasses to modify behavior. This applies to the jME games, game states,
JMEDesktop.
If a class is made to facilitate subclassing, then (1) if it's likely that a member
needs to be even just read by a subclass, then it should be protected not
private, or at least provide getters and setters for critical components; and
(2) there should be at least one constructor provided that does not apply all
"settings". To clarify the second point, I'll give an example.
Darkfrog and others on the development team seem to prefer not subclassing
StandardGame, but StandardGame is designed so that you can do very little
without not only subclassing, but without either duplicating much of the
original class or replacing it entirely. Here is the most trivial
customization I can think of: I want my code to specify whether to display the
game settings dialog, (for example if a user gives a command-line switch to my
game, or if they click a button on the login screen). It is impossible to do
this without replacing (not just subclassing) the StandardGame class. The
work-around I have used so far is to zero the Java Preferences object, but that
is a bad work-around, since the user usually wants to adjust existing settings,
not start from scratch. StandardGame will run the settings dialog if there are no
settings and will not otherwise.
You can't adjust this behavior because there is no opportunity to modify any
instance behavior since everything is done inside the constructor. If you
subclass, you still have to super to one of the provided StandardGame
constructors. A year or so ago I did a minor refactor to the games to make
proper use of the GameSettings interface, and you can see my comment from
when I did that work in StandardGame.java: you have to subclass to modify
settings dialog behavior… but what I didn't mention at the time (my target
at the time was not with subclassing), was that you have to duplicate half of
the class in order to subclass.
I think jME would benefit greatly if the central classes would use the
following idiom:
public initialized = false;
// "initialized" signifies that instance is constructed and ready for use.
protected int width;
// "width" starts at 0 here, so must be set somehow before instance is initialized
protected ConfigShowMode configShowMode = DEFAULT_CONFIG_SHOW_MODE;
/** Convenience constructor */
publid AClass(int width, int height) {
setWidth(width);
..
/** JavaBean constructor */
public AClass() {
}
protected void oneOfMultipleSetupMethods() {
// A method to set up the screen, for example.
// It is protected so that subclasses may override and super() it,
// or make their own constructor that invokes it.
if (... Verify that required properties have been set before using
protected init() {
if (width < 1 ||...) { // Validate that critical settings have been made
throw new IllegalStateExceptin(
"A required property has not been set. One of..."0;
// Do all the work that is currently in the base jME constructors
...
oneOfMultipleSetupMethods();
twoOf...
initialized = true;
}
public void setWidth(int width) {...
// Allow user the opportunity to modify the instance assembly before it
// is too late. Use setters for everything that can be modified.
public void setConfigShowMode(...
public void businessMethod() {
if (!initialized) {
throw IllegalStateException("Instance not initialized");
This is worlds better in both respects:
- Users can modify the behavior using the setters, without subclassing at all.
- When a user needs to subclass, they get optimal code re-use since the meat
of the code is "protected".