views:

78

answers:

4

I have an abstract base class that many classes extend. I'd like all these classes to define a unique value for a specific property that is originally defined in the base class (similar to the serialVersionUID property that causes a warning when not defined in classes that inherit from Serializable).

Is there a way for me, within my abstract base class, to declare a property that does not have a value, but requires all extended classes to define a value for it?

Note that the value does not have to be associated with each individual instance, i.e.: it can be defined as static.

Edit: I guess a more basic question I should also ask, since the answers vary so widely, is how does Java implement serialVersionUID (in terms of its signature) such that my IDE raises warnings when it's not defined?

+1  A: 

Hardly. I'd suggest putting user instructions in your base class' javadoc and checking if property is present before using it: object.class.getDeclaredField("MY_CONSTANT")

I think, Serializable interface is a good example of such approach.

Nikita Rybak
Perhaps verifying the presence of the field in the super constructor might be appropriate.
meriton
+1  A: 

Reposting to match the criteria I missed:

public abstract class Abstract {

    private static int field;

    public Abstract(int aValue) {
        field = aValue;
    }

    public int getField() {
        return field;
    }
}

public class Child extends Abstract {

    private static final int value;

    static {
        value = 10; //Pick a value for each class.
    }

    public Child() {
        super(value);
    }
}
Mike
This is essentially what I'm doing right now, except my `Child()` constructor takes no parameters, calling `super()` with the `aValue` property defined in the call to super itself. It seems like more of a hack than what I would think are other possibilities, though.
Matt Huggins
Also good way. But he says he needs one value per class (not object), so _Child_ constructor doesn't really need parameter.
Nikita Rybak
Good point. I missed that, Nikkita.
Mike
Well, you and I came up with the same solution. Call it a hack, but it felt natural to me. :)
Mike
@Mike I think it's perfectly fine :) The only downside I see is that it requires base superclass instead of just common interface.
Nikita Rybak
I agree, Nikita. I suppose the real question is, how do we raise compiler warnings by ourselves?
Mike
A: 

Something like the following is a typical approach to this:

public abstract class Superclass {

    private final String something;

    public Superclass(String something) {
        this.something = something;
    }

    public String getSomething() {
        return something;
    }
}

public class Subclass {

    public Subclass() {
        super("a value for something");
    }
}

You don't get to have a static property value though.

Steve McLeod
A: 

Fields can not be overridden, but methods can. If you need not enforce that the value is constant, use:

class Super() {
    /**
     * @return the magic value
     */
    abstract MyType getValue();
}

If you do need to enforce that the field is final, you can give each instance its own copy/reference as in the answers of Steve or Mike.

If you can't do that either you can do crazy stuff like:

class Super() {
    private static Map<Class<? extends Super, MyType> map = new ...;

    protected Super(MyType value) {
        if (!map.contains(getClass())) {
            map.put(getClass(), value);
        } else {
            assert map.get(getClass(), value) == value;
        }
    }
}
meriton