Java – Limitations of Polymorphism in statically typed languages

cdesignjavajavascriptpolymorphism

I program mostly in statically typed languages, like C++ and Java. A common strategy employed in languages like these to handle dealing with collections of objects which are related, but which need to employ specific behaviors, is to use polymorphism and inheritance hierarchies. But Polymorphism only works when the Base class has a method (virtual function) which can then be overridden by every Derived class. But there are often cases where a Derived class needs to have a method, and it doesn't make sense to place a method of the same name in the Base class, because it is very specific to the Derived class.

Let me give a concrete example that many of us can probably relate to: the HTML DOM.

Javascript programmers are quite used to doing things like iterating over collections of DOM nodes. They take for granted the dynamically-typed nature of Javascript when they do something like:

node = document.getElementById("foo");
for (var i = 0; i < node.childNodes.length; ++i) 
    doSomething(node.childNodes[i]);

Something like this would be very messy to do in a statically typed language like Java, because inheritance-based polymorphism doesn't lend itself well to situations where Derived classes have methods which don't exist in the Base class. For example, when iterating over the above HTML Nodes, we might find a DIV node, which has certain methods, and a Text node, which has certain different methods, and a TABLE node, which has its own unique methods – and it wouldn't make much sense for ALL of these various methods to exist in a common Base class "Node", because they are highly specific to each Derived type. (e.g. a DIV node has no need of a "cells" method, but a TABLE node does.)

So, in a statically typed language, you'd be forced to fall back on something like Type Enums and a lot of messy down-casting to check what type of Node you have. So basically you end up with messy code like:

Node node = document.getElementById("foo");
for (int i = 0; i < node.childNodes().length(); ++i) 
{
   Node n = node.childNodes().elementAt(i);
   if (n.type() == Node.DIV_NODE) doSomethingWithDiv(((DivNode)(n)));
   else if (n.type() == Node.TABLE_NODE) doSomethingWithTable(((TableNode)(n)));
   /* etc... */
}

This is similar to what C programmers do, and it's seemingly the sort of thing virtual functions were designed to avoid. And yet, when you're faced with a situation where there are various different methods in a Derived class for which it doesn't make any sense to place in a common base class, you have no recourse but to resort to something like Type Enums.

So, how is this problem usually addressed in statically-typed languages? Is there a better design pattern than Type Enums?

Best Answer

This isn't a limitation in statically typed languages, there exists a solution to this problem which is to declare a common Interface between the various classes for the operations that you care about. This allows you to do whatever you need to do, while still being type safe.

Related Topic