Note that there are some explanatory texts on larger screens.

plurals
  1. POUsing Public Final Member Variables and Overridable Methods in a Constructor
    primarykey
    data
    text
    <p>I have questions about a couple techniques I'm using in designing a class. I've declared some of its members as public final instead of private, and the constructor calls overridable methods. I know that these are normally considered bad practice, but I think that they may be justified in my situation, and I want to know what others think.</p> <p>This is my class:</p> <pre><code>/** A monster that fights other monsters in my program */ public abstract class Creature { /** * Keeps track of the different values determining how powerful a Creature * is. */ public static class Stats { //subclass definition here. //This subclass contains a lot of public static members like this: public final CurMax health; } public final static Random RANDOM = new Random(); //These are the public final members that I'm wondering about. public final Stats stats; public final Attack[] attacks; public final Stopwatch turnStopwatch; private String name; //This is the constructor I'm wondering about. public Creature() { initMembers(); stats = generateStats(); name = RandomValues.NAMES[RANDOM.nextInt(RandomValues.NAMES.length)]; attacks = generateAttacks(); turnStopwatch = new Stopwatch(false); } /** * Define any member variables for subclasses in Creature in this method, * not in the subclasses' constructors. * * Using the Creature class requires the Constructor to call overridable * methods. This is deliberate because the constructor assigns values to * final member variables, but I want the values of these variables to be * determined by subclasses. This method allows subclasses to assign values * to their own member variables while still controlling the values of the * final variables in the Creature class. * * @see #generateAttacks() * @see #generateStats() */ protected abstract void initMembers(); protected abstract Stats generateStats(); protected abstract Attack[] generateAttacks(); public boolean isDead() { return stats.health.getCurrent() &lt;= 0; } public String getName() { return name; } } </code></pre> <p><p> I declared the member variables as public final because I plan on using them frequently and creating methods to control access to them would be tedious. For example, I plan on writing lines like this throughout the program:<br> <code>creature.stats.health.getCurrent();</code><br> <code>creature.stats.health.resetMax();</code><br> Avoiding giving public access to stats and health would require writing methods like <code>getCurrentHealth()</code> and <code>resetMaxHealth()</code> throughout the Creature class. The CurMax class has 10 methods besides constructors, and the stats class has 12 members of types that are similar to CurMax, so that would require writing over 100 additional functions in the Creature class. In light of this, is the way I used public final members appropriate? If it isn't, what would be another technique that would be more satisfactory?</p> <p>If the use of public final members is fine, what about my use of overridable methods in the constructor? I want to allow each subclass of Creature to determine its own algorithm for creating the stats and array of attacks. For example, one creature might pick some random attacks out of a list, while another chooses attacks that are effective against another specific creature. Since <code>stats</code> and <code>attacks</code> are final variables, though, they must be defined in Creature's constructor. My workaround is to have the constructor call overridable methods to allow subclasses to determine the values of <code>stats</code> and <code>attacks</code> while leaving the actual assignment in the constructor.</p> <p>I understand that the main risk associated with using overridable methods in constructors is that the overriden methods will be called before the subclass has an opportunity to define its own data members. I think that this is avoided in my situation because the generateStats() and generateAttacks() methods are there only to be used in the constructor. Also, I added another abstract method, initMembers, that is called in the Creature constructor before anything else. Subclasses can define any member variables in this function before generateStats() and generateAttacks() are called.</p> <p>The constructors for Stats and Attack are large, so I can't simply pass a Stats object and an array of Attacks to the constructor. The call to super() in the subclasses' constructors would be unacceptably long.</p> <p>Is the way I'm using overridable methods in the Creature constructor justified? If it isn't, what else should I do?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload