He Joel,
Let me see if I understand you correctly.
Basically you suggesting two kind of solutions:
1) Introducing interfaces like requested in the issue.
2) Using generics.
My 50 cent:
2) I would't go there for the reasons you gave above. It get scary,
also if you think about it that there are still many developers that
don't really understand the details of Generics and rather avoid
them....
1) Introducing interfaces seems like a good solution to me.
Wny?:
- Instead of with Generics, if you don't want to use them, you don't
need to. They are just mindless "things" that are out there and you
can use them to compose your components, but you don't need to if you
don't want to..
> It doesn't appear to me that creating an "IWidget" base interface for
> widgets would really help much here. You'd end up having to create a baroque
> type hierarchy something like this:
I don't really understand you point here?
I understand that it gives a lot of extra interfaces, but isn't that
the consequence of:
a) Java, not being able to extend more then one class?
b) Necessary if you want to offer an extendable/user-friendly/
flexible/... API?
Especially this last point is important I think. Just have a look at
the Spring framework. They have two hierachies: one for the classes
and one for the interfaces.. You easily lose overview but the
interfaces give a lot of flexibility to extend the Spring framework
and add your own components.
I would have had great problem if they wouldn't have done that.. As
such I think you can't do without a clear hierachy of interfaces if
you want to comply b).
From a design point of view: I also think it gives you a good overview
of what you framework really offers and can be extended.
I wouldn't like to think of the java SE Collection framework without
the interfaces :(
Your example showed the problem well, but let me point out some more
to show the ugly coding of no-interfaces:
I have a WidgetGroup class with Widget CRUD actions. Snippet:
public class WidgetGroup {
/**
* @param widget
* must implement {@link ItemSelectable}
*/
public void addWidget(final Widget widget) {
assert widget instanceof ItemSelectable: "boem";
.....
}
/**
* @param widget
* must implement {@link ItemSelectable}
*/
public void insertWidget(final Widget widget) {
assert widget instanceof ItemSelectable: "boem";
.....
}
....
...
}
As you can see: the specified widget must implement ItemSelectable.
Snippet:
public interface ItemSelectable extends SourcesClickEvents, HasData {
void setSelected(boolean selected);
boolean isSelected();
void setEnabled(boolean enabled);
boolean isEnabled();
}
I think you see where I am going. Everytime I have to check if it
implements the correct interface :(... I can tell you that I do these
constructions a lot as I did a lot of coding already... I have more
examples like MutationList, ButtonBar, which all have the same kind of
constructions... If you want more examples, just let me know please?
Another snippet about a Slide In effect:
public void slideInPanel(final Panel mainPanel, final Widget widget,
final SlideInSpeed style, final int index) {
if (index == -1) { // add at end
mainPanel.add(widget);
}
else {
if (mainPanel instanceof FlowPanel) {
((FlowPanel) mainPanel).insert(widget, index);
}
else if (mainPanel instanceof HorizontalPanel) {
((HorizontalPanel) mainPanel).insert(widget, index);
}
else if (mainPanel instanceof VerticalPanel) {
((VerticalPanel) mainPanel).insert(widget, index);
}
else {
throw new CodeRuntimeException("err-effects-01", " panel type: " +
mainPanel.getClass().getName());
}
}
// slide the widget into his parent
Effects.slideIn(widget.getElement(), createEffectConfig(style),
Direction.DOWN);
}
Beautiful coding not? :(
This is also solved if I simple would have an interface like suggested
in issue 1112, like mentioned by Fred:
http://code.google.com/p/google-web-toolkit/issues/detail?id=1112