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
}
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.