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

Time:09-19

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?

CodePudding user response:

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;
        }
    }
}

CodePudding user response:

You can pass the command name via the super's constructor.

abstract class Command {
    public String commandName; 

    protected Command(String name) {
       this.commandName = name;
    }
    
    public String getName(){
       return commandName;
    }
    
    public static final class Help extends Command {
        public Help() { super("help"); }
    }

    public static final class Select extends Command {
        public final int choice;
        public Select(int choice) {
            super("select");
            this.choice = choice;
        }
    }
}
public class Main{
    public static void main(String[] args) {
      Command c1 = new Command.Help();
      System.out.println(c1.getName());
      Command c2 = new Command.Select(2);
      System.out.println(c2.getName());
    }
}
  • Related