Kilokahn
Kilokahn

Reputation: 2311

Java - How to get concrete parameter type when overriding interface method of generic type

I am a generics newbie and I am not able to find out the best way to achieve this. Please feel free to point out if I am doing something obviously wrong.

interface Node<T> {

    void addOne(Node<T> node);
}

class StringNode implements Node<String> {

    List<StringNode> data = new ArrayList<>();

    /**
     * {@inheritDoc}
     */
    @Override
    public void addOne(Node<String> node) {
        StringNode stringNode = (StringNode) node;
        data.add(stringNode);
    }

}

I was hoping to find a way to avoid the downcast from Node to StringNode in the implementation of addOne by having the function itself be of signature public void addOne(StringNode node). Any ideas as to how the definition of Node can be changed to achieve this for any implementation of the interface?

I tried searching through the questions already asked, but was not able to find a close match. Any pointers to questions where this has already been discussed would also be greatly appreciated.

Thanks in advance!

Upvotes: 3

Views: 978

Answers (3)

Gustav Karlsson
Gustav Karlsson

Reputation: 1221

This is how I would have done it:

interface Node<T extends Node<T>> {

    void addOne(T node);
}

class StringNode implements Node<StringNode> {

    List<StringNode> data = new ArrayList<StringNode>();

    /**
     * {@inheritDoc}
     */
    @Override
    public void addOne(StringNode node) {
        data.add(node);
    }

}

Similar to U-No-Poo's suggestion, but a little more strict (forces T to actually be a node)

Upvotes: 2

tehlexx
tehlexx

Reputation: 2859

You could introduce another generic parameter:

public interface Node<VALUE_TYPE, SELF> {
  public void addOne(SELF u);
}

public class StringNode implements Node<String, StringNode> {

  @Override
  public void addOne(StringNode u) {
    // TODO Auto-generated method stub  
  }
}

Use VALUE_TYPE whenever you need the actual value type (in this case String) and SELF whenever you want to pass a node of that type.

Upvotes: 1

Scorpio
Scorpio

Reputation: 2327

Why are you using String and StringNode separatly? Couldn't you just say

interface Node<T> {

    void addOne(T node);
}

class StringNode implements Node<StringNode> {

    List<StringNode> data = new ArrayList<StringNode>();

    /**
     * {@inheritDoc}
     */
    @Override
    public void addOne(StringNode node) {
        StringNode stringNode =  node;
        data.add(stringNode);
    }

}

Upvotes: 3

Related Questions