Tomáš Zato
Tomáš Zato

Reputation: 53193

How to make <T extends E> generic type argument inclusive?

I have an interface:

  /**
   * Getter for any values within the GameObject and it's subclasses. 
   * Used as callback.
   * 
   * Typical implementation would look like:
   *   new ValueGetter<SummonerSpell, String> {
   *     public String getValue(SummonerSpell source) {
   *       return source.toString();
   *     }
   *   }
   * @param <T> 
   * @param <V> Type of value retrieved
   */
  public static interface ValueGetter<T extends GameObject, V> {
    public V getValue(T source);
  }

In one case I want to use the interface with GameObject itself, rather than some subclass. I want to do this in a List of game objects:

  /**
   * Will call the given value getter for all elements of this collection and return array of values.
   * @param <T>
   * @param <V>
   * @param reader
   * @return 
   */
  public <T extends GameObject, V> List<V> enumValues(ValueGetter<T, V> reader) {
    List<V> vals = new ArrayList();

    for(GameObject o : this) {
      vals.add(reader.getValue(o));
    }
    return vals;
  }

But reader.getValue(o) causes compiler error:

incompatible types: GameObject cannot be converted to T
  where T,V are type-variables:
    T extends GameObject declared in method <T,V>enumValues(ValueGetter<T,V>)
    V extends Object declared in method <T,V>enumValues(ValueGetter<T,V>)

My problem as image:

image description

Upvotes: 5

Views: 1467

Answers (3)

Hussein Zawawi
Hussein Zawawi

Reputation: 2937

I dont think there is a way to ashieve this in Java. one suggestion is to have wrapper type on top of GameObject.

Upvotes: 0

Luciano
Luciano

Reputation: 8582

T may be a GameObject, or a child of it. Let's say the child name is NPCObject. So you call enumValues with T as NPCObject.

ValueGetter may be optimised for NPCObjects, so you can't actually call it with a GameObject! What is ValueGetter going to do with that?

ValueGetter deals with T (a NPCObject in this case). The type < T extends GameObject > mentions one type: T. It doesn't say: all types that are GameObject or descendants of it. T is fixed and the method itself doesn't know what it is.

Upvotes: 0

user2418306
user2418306

Reputation: 2382

public <T extends GameObject, V> List<V> enumValues(List<T> list, ValueGetter<T, V> reader) {
    List<V> vals = new ArrayList();

    for(T o : list) {
        vals.add(reader.getValue(o));
    }
    return vals;
}

Upvotes: 2

Related Questions