ubanerjea
ubanerjea

Reputation: 474

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!

Upvotes: 4

Views: 1757

Answers (3)

lmm
lmm

Reputation: 17431

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

Upvotes: 1

Kirill Shalnov
Kirill Shalnov

Reputation: 2216

You can make constants private and use getter to access them

public abstract class MessageField {
     private final int fieldId = 1; 
     private final String tag = "->"; 
     public int getFieldId();
}

public class TypeOne extends MessageField { 
    private final int fieldId = 1; 
    private final String tag = "->";

    public int getFieldId() {
        return fieldId;
    }
}

public class TypeTwo extends MessageField { 
    private final int fieldIdOLOLO = 2;
    private final String tag = "->"; 

    public int getFieldId() {
       return fieldIdOLOLO;
    }
}


public class TypeThree extends MessageField { 
    private final String tag = "->"; 

    public int getFieldId() {
        return 5;
    }
}

Upvotes: 0

Ted Hopp
Ted Hopp

Reputation: 234795

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.

Upvotes: 8

Related Questions