1

I currently have a Tile class that extends a Node class, and want to downcast an array of Nodes to an array of Tiles like so:

class Node<T> {
  Node[] neighbours;
  private final T value;
}

class Tile extends Node {

  public Tile(Point value) {
    super(value);
  }

  Tile[] neighbours = (Tile[]) this.getNeighbours;
}

At the moment the compiler is throwing A ClassCastException and I do not know how to fix it.

I am not 100% familiar with inheritance, but I thought since Tile is a subclass this should be a safe casting from Nodes to Tiles.

Zac Sanchez
  • 71
  • 1
  • 1
  • 8
  • 2
    And what is the question? – Alexey Romanov May 27 '18 at 10:55
  • It is same rule as with `Tile child = (Tile) new Node();`. It wouldn't be typesafe to let `child` hold `Node` instance because it is possible that `Tile` has some methods/fields which `Node` doesn't. Lets say we call `child.setPropertyAddedInTile(valie)`, how that code should be executed on `Node` instance which doesn't have such *property*? – Pshemo May 27 '18 at 11:09

2 Answers2

3

If Tile is a sub-class of Node, all Tiles a Nodes, but not all Nodes a Tiles.

Therefore casting a Node[] to Tile[] is wrong, since not all Node arrays are Tile arrays.

For example, the following will throw ClassCastException:

Node[] nodes = new Node[10];
Tile[] tiles = (Tile[]) nodes;

On the other hand, the following will work:

Node[] nodes = new Tile[10];
Tile[] tiles = (Tile[]) nodes;
Eran
  • 387,369
  • 54
  • 702
  • 768
  • @ZacSanchez that depends on the use case. From the little code you posted, it's hard to say. When ans how is the `neighbours` variable initialized in the `Node` class? And why would you want an instance variable of the same name and (possibly) same data in the `Tile` sub-class? – Eran May 27 '18 at 11:05
0

You could use a collection, for example something like:

class Node<T> {
    List<Node> neighbours;
    private T value;
}

class Tile extends Node {

    public Tile(String value) {
        super(value);
    }

    List<Tile> neighbours = this.neighbours.stream().filter(item -> item instanceof Tile).map(item -> (Tile) item).collect(Collectors.toList());
}