Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Final constant values with inheritance in Java?

I have the following problem. I want one broad abstract type called MessageField. The run-time use of the MessageField is to carry around a String value; the rest of the type should be a bunch of constant definitions and behavior. Each subclass of MessageField should be a set of constant final members that define the type and, if necessary, can also override other behavioral methods.

So for example:

public abstract class MessageField {
   //whatever needs to go here to make this work
   //methods that define behavior
   //e.g. public int getFieldId() { return fieldId; }
}

public class TypeOne extends MessageField { 
    public final int fieldId = 1; //type defining member
    public final String tag = "->"; //type-defining member
    public String fieldValue; //freely settable/gettable
    //change any behavior if necessary
}

public class TypeTwo extends MessageField { 
    public final int fieldId = 2;
    public final String tag = "++";
    public String fieldValue;
}

public class TypeThree extends MessageField {
    public final int fieldId = 3;
    public final String tag = "blah";
    public String fieldValue;
}

Each subclass should be forced to define a value for fieldId and tag when it's written. I guess conceptually these are static final constants for each type, but how does that work with inheritance? I need all the various types to conform to one broad overarching type which can be passed around.

Maybe inheritance isn't the best way to accomplish this pattern, but if not, what is? And if inheritance is the way to do this, how would it be done?

Thanks!

like image 781
ubanerjea Avatar asked Jan 09 '23 06:01

ubanerjea


2 Answers

Move the fields up to the base class and initialize them through a constructor:

public abstract class MessageField {
    public final int fieldId;
    public final String tag;

    protected MessageField(int fieldId, String tag) {
        this.fieldId = fieldId;
        this.tag = tag;
    }

    public int getFieldId() {
        return fieldId;
    }

    public String getTag() {
        return tag;
    }
}

public class TypeOne extends MessageField {
    public String fieldValue; //freely settable/gettable

    public TypeOne() {
        super(1, "->");
    }
}

// etc.

Since you contemplate having accessor methods, I'd suggest making fieldId and tag private.

like image 169
Ted Hopp Avatar answered Jan 18 '23 22:01

Ted Hopp


There's no way to require subtypes to have static values or otherwise conform to any interface, this is why e.g. Factory objects are objects in their own right.

One useful trick Java does have is that Enums are first-class objects. What about moving the static parts of each MessageField into an Enum?

public enum MessageFieldType {
  public abstract int getFieldId();
  ...

  ONE {
    public int getFieldId() { return 1; }
    ...
  },
  TWO { ... }, ...
}

public class MessageField {
  public final String value;
  public final MessageFieldType fieldType;
  ...
}
like image 44
lmm Avatar answered Jan 18 '23 22:01

lmm