Edited:\" I received a very pertinent answer from \'erickson\', but there is a side problem (up-casting?) that was not explicitly covered in my original
You can make generic methods as well as generic types. Using these, the problem methods in GraphUtils can be fixed like this:
static > void addNewNeighbors1a(T node, T newNode)
{
node.addNeighbor(newNode);
print("Add city to node", node.neighbors());
}
static > void addNewNeighbors2(T node, T newNode)
{
node.addNeighbor(newNode);
print("Add concrete node to node", node.neighbors());
}
Hey, wait a second… those are the same methods!
It turns out that, since they only depend on the interface of Node, you only need one of them to handle any Node implementation.
Down the road, you might find it necessary to change the Node interface like this:
public abstract void addNeighbor(S n);