views:

241

answers:

3

Good evening,

I am developing a set of Java classes so that a container class Box contains a List of a contained class Widget. A Widget needs to be able to specify relationships with other Widgets. I figured a good way to do this would be to do something like this:

public abstract class Widget {
    public static class WidgetID {
        // implementation stolen from Google's GWT
        private static int nextHashCode;
        private final int index;

        public WidgetID() {
            index = ++nextHashCode;
        }

        public final int hashCode() {
            return index;
        }
    }

    public abstract WidgetID getWidgetID();

}

so sublcasses of Widget could:

public class BlueWidget extends Widget {
    public static final WidgetID WIDGETID = new WidgetID();

    @Override
    public WidgetID getWidgetID() {
        return WIDGETID;
    }
}

Now, BlueWidget can do getBox().addWidgetRelationship(RelationshipTypes.SomeType, RedWidget.WIDGETID, and Box can iterate through it's list comparing the second parameter to iter.next().getWidgetID().

Now, all this works great so far. What I'm trying to do is keep from having to declare the public static final WidgetID WIDGETID in all the subclasses and implement it instead in the parent Widget class. The problem is, if I move that line of code into Widget (along with the implementation of getWidgetID()), then every instance of a subclass of Widget appears to get the same static final WidgetID for their Subclassname.WIDGETID. However, making it non-static means I can no longer even call Subclassname.WIDGETID.

So: how do I create a static WidgetID in the parent Widget class while ensuring it is different for every instance of Widget and subclasses of Widget? Or am I using the wrong tool for the job here?

Thanks!

[Edit] I would prefer not to require users of the library to call super() in all their sub-Widget constructors.

+3  A: 

If every subclass has a different value, the variable isn't a member of the superclass.

In other words, yes, each subclass should declare its own WIDGETID; you cannot consolidate those members of various classes as a single member in a superclass.

erickson
Marked as the correct answer since it answers the question proposed, although other answers provided useful ideas.
BinaryMuse
+5  A: 

Since it seems like the idea is that the WidgetID be unique for each specific subclass, why don't you just identify them by their class instead?

So where you are doing getBox().addWidgetRelationship(RelationshipTypes.SomeType, RedWidget.WIDGETID) you could do getBox().addWidgetRelationship(RelationshipTypes.SomeType, RedWidget.class) instead.

ColinD
I actually like this method; if Google Web Toolkit supports this, it sounds ideal. Can you specify that a method should only accept `Class` objects that come from `Widget` or its subclasses? E.g., so that one couldn't pass in `someRandomObject.class`?
BinaryMuse
Binary: Yes, declare the parameter as `Class<? extends Widget>`
meriton
A: 

Why not just declare an abstract method within Widget such as:

protected abstract WidgetID getWidgetID();

This way, each subclass must implement the method and return its own value. You can still declare WidgetID to be static within the subclasses, but the above instance method to return the 'unique' value.

Jason Nichols
With that interface, you can only refer to a widget if you already have an instance of that widget. In his example, knowing the class was enough.
meriton
This functionality (Jason's original answer) is how things currently work in my question. Perhaps that is a sign. :)
BinaryMuse