1

I’ve extended some of the base classes of Apache Olingo 4 (still in development) to allow for stronger typing. However, my use of generics is causing an error that I didn’t expect.

I have a type parameter E that extends FooODataEntity which in turn implements the ODataEntity interface. Since FooODataEntity is an ODataEntity (just more specific) I would expect this to compile with no issues. However, getEntities() has a compilation error as shown in the code below.

Also, I would expect to be able to specify List<E> as a return type for my override of getEntities() but then I get a compile error saying:

'getEntities()' in 'com.foo.restapi.client.olingo.FooEntitySet' clashes with 'getEntities()' in 'org.apache.olingo.commons.api.domain.v4.ODataEntitySet'; attempting to use incompatible return type

What am I missing here?

FooODataEntitySet:

package com.foo.restapi.client.olingo;

import com.foo.restapi.client.FooODataEntity;
import com.foo.restapi.client.exceptions.FooRuntimeException;

import org.apache.olingo.commons.api.domain.v4.ODataAnnotation;
import org.apache.olingo.commons.api.domain.v4.ODataEntity;
import org.apache.olingo.commons.api.domain.v4.ODataEntitySet;
import org.apache.olingo.commons.core.domain.AbstractODataEntitySet;

import java.lang.reflect.Constructor;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

public class FooEntitySet<E extends FooODataEntity> 
        extends AbstractODataEntitySet implements ODataEntitySet {

    private final List<E> entities = new ArrayList<E>();

    public FooEntitySet() {
        super();
    }

    @Override
    public List<ODataEntity> getEntities() {
        // compile error  
        // Incompatible types. Found: 'java.util.List<E>', 
        // required: 'java.util.List<org.apache.olingo.commons.api.domain.v4.ODataEntity>'

        return entities;
    }
}

FooODataEntity:

package com.foo.restapi.client;

public class FooODataEntity extends AbstractODataPayload 
        implements ODataEntity, ODataSingleton {

    // code not shown
}
Anthony Elliott
  • 2,941
  • 5
  • 29
  • 42

1 Answers1

1

There's a reason you can't do this. While a FooODataEntity is an ODataEntity, a List<FoodODataEntity> is not a List<ODataEntity>.

Lets cover that in more detail:

Say I have this class:

public class BaconODataEntity implements ODataEntity {
    // Pretend I implement all the ODataEntity things
}

I can add an instance of BaconODataEntity into a List<BaconODataEntity> and a List<ODataEntity>... but not into a List<FooODataEntity>.

So, simply letting you cast a List<FooODataEntity> to a List<ODataEntity> would destroy the very type safety that generics are meant to introduce as I could then add a BaconODataEntity to it

So, how do you fix it? Well, if you absolutely need your List to be a List<E extends FooODataEntity>, create a new List and copy the elements into it and return that list.

Community
  • 1
  • 1
Powerlord
  • 87,612
  • 17
  • 125
  • 175