Search code examples
javaclassstaticabstract-classsoftware-design

How to make field in abstract class common in inner classes without making static?


Suppose I have the following abstract class with nested static classes:

/**
 * Command class.
 */
public abstract class Command {
    public String commandName; // The name of the command.

    private Command() {}

    /**
     * Help command.
     */
    public static final class Help extends Command {
        public Help() { this.commandName = "help"; }
    }

    /**
     * Selection command.
     */
    public static final class Select extends Command {
        public final int choice;
        public Select(int choice) {
            this.commandName = "select";
            this.choice = choice;
        }
    }
}

I want the ability to access the field commandName from the Help and Select classes through Command.Help.commandName, for example. Unfortunately I can't seem to do this because the commandName field is not static. Let's say I "fix" this issue by making commandName static. The next problem arises when I run the following block of code:

Command c1 = new Command.Help();
System.out.println(Command.Help.commandName);
Command c2 = new Command.Select();
System.out.println(Command.Help.commandName);

This block outputs

help
select

when I would have expected

help
help

because I want the respective command names for Help and Select to stay fixed no matter what instances of either command I instantiate. Is the only solution to create a commandName field for every class, or is there a less repetitive way to do this?


Solution

  • Just shadow the commandName field

    /**
     * Command class.
     */
    public abstract class Command {
        public String commandName; // The name of the command.
    
        private Command() {}
    
        /**
         * Help command.
         */
        public static final class Help extends Command {
            public static final String commandName = "help"; // Command.Help.commandName will reach this
            public Help() {  }
        }
    
        /**
         * Selection command.
         */
        public static final class Select extends Command {
            public static final String commandName = "select"; // Command.Select.commandName will reach this
    
            public final int choice;
            public Select(int choice) {
                this.choice = choice;
            }
        }
    }