1

I have two classes. An interface class "Node" and "Nodegraph" that implements "Node". "Node" has one parametric method, add, where I use Node node as paramenter. In NodeGraph, I need to casting (NodeGraph) node in order to use NodeGraph object. Is there a better way to avoid casting?

import java.util.Set;

public interface Node {
    public String getId();
    public void add(Node node);
    public boolean remove(Node node);
}


import java.util.Iterator;
import java.util.LinkedList;

public class NodeGraph implements Node {

    private int row;
    private int column;
    private String id;
    private LinkedList<NodeGraph> neighbourds = new LinkedList<NodeGraph>();

    public NodeGraph(int row, int column) {
        this.row = row;
        this.column = column;
        id = "" + row + column;
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public void add(Node node) {
        neighbourds.add((NodeGraph) node);
    }

    @Override
    public boolean remove(Node node) {
        return neighbourds.remove((NodeGraph) node);
    }

}
Gianni Spear
  • 7,033
  • 22
  • 82
  • 131

3 Answers3

4

I assume you have valid reasons to keep neighbourds list bound to NodeGraph type. If so here is how you can avoid casting by parametrizing the Node interface:

public interface Node< T extends Node<T> > {
    public String getId();
    public void add(T node);
    public boolean remove(T node);
}

public class NodeGraph implements Node<NodeGraph> {

    private int row;
    private int column;
    private String id;
    private LinkedList<NodeGraph> neighbourds = new LinkedList<NodeGraph>();

    public NodeGraph(int row, int column) {
        this.row = row;
        this.column = column;
        id = "" + row + column;
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public void add(NodeGraph node) {
        neighbourds.add(node);
    }

    @Override
    public boolean remove(NodeGraph node) {
        return neighbourds.remove(node);
    }
}
tsolakp
  • 5,858
  • 1
  • 22
  • 28
  • Are there any performance benefits by avoiding the casting as well? I've seen this type of pattern in Scala, can you recommend some good resources to look into type bounds for Java? – Bar Mar 20 '18 at 10:31
3

That happens because you neighbourds list is invariant, this means that you could insert the parametrized type only, which is NodeGraph in this case, defining the list as covariant to Node would let you add any subclass of Node:

private LinkedList<? extends Node> neighbourds = new LinkedList<>();
AlexITC
  • 1,054
  • 1
  • 10
  • 21
2

You should declare the neighbors list using the interface (for both List and Node):

private List<Node> neighbourds = new LinkedList<>();
Costi Ciudatu
  • 37,042
  • 7
  • 56
  • 92
  • thanks but I get an error when i change private LinkedList neighbourds = new LinkedList(); in private List neighbourds = new LinkedList<>(); or maybe I didn't get your help – Gianni Spear Nov 10 '17 at 22:36
  • What seems to be the error? I can only assume it has to do with the "diamond" operator and the language level of your project being 1.6 or below). If so, use `new LinkedList()` or (far better) upgrade to java8. Also note that you must import `java.util.List` for this to work. – Costi Ciudatu Nov 10 '17 at 22:44