Joe's Java and Web Jottings

your host


Your Host

Calendar

««Nov 2009»»
SMTWTFS
1234567
891011121314
15161718192021
22232425262728
2930

My Top Tags

               

Java Libs and Tools

My Other Pages

My RSS Feeds








an API to bite one in the arse

posted Friday, 28 January 2005
One of the biggest problems with inheritence for the sake of code reuse is that you can often inherit methods that no longer have any validity in the derived class, yet nothing in the compiler can tell you that unless the derived class goes out of its way to override the method and add a "@deprecated" sign to it.  Even then, sections of your code may never get the warning if they refer to the object by its base class anyways (Base b = new Derived()).

Case in point, JDBC.

PreparedStatement logically shares a lot from Statement, from a conceptual level, so it makes sense to have PreparedStatement derive from Statement.  However, one method in Statement, if called by a PreparedStatement, utterly breaks every time you use it, assuming you're using PreparedStatement the way it was intended:  executeQuery(String query).

If you've gone to the trouble of creating a PreparedStatement using the factory method in Connection, and setting the parameters, you can still accidentally call that version of the method instead of the appropriate executeQuery() with no parameters.  This will immediately get the runtime error of "not all variables bound", which at first glance of the code makes no sense, since you can see right there that you've set all the parameters.

All because there's no way for the compiler to tell you that method has no meaning in the derived class.  Even in the case of having no parameters to set, the presense of the method in PreparedStatement is useless because it wastes the entire step of "preparing" the query in the first place.  it actually evaluates the query *twice*, once at construction, then once again at the execute, since it has no real way of knowing that they are the same thing.

API designers, keep that in mind.  If you want to share interfaces through inheritence, but one derived interface might make an inherited method invalid/useless, then refactor -- create a base class with the common methods, and then derived classes with the additional methods that make sense.

Compilers should be able to catch mistakes like this, but they can't when you don't construct your hierarchies correctly.




1. a reader left...
Friday, 28 January 2005 2:18 pm

I think this is one of Swing's biggest problems. You can call setVisible on a popup menu, but it doesn't do anything, it's an inherited method whose functionality is implemented in another popup-specific method.

Keith Michael Lea [keith@cs.oswego.edu]