简体   繁体   中英

Casting Object From Class To Fit Generic

I have a Map that receives a Class<? extends EntityBase> Class<? extends EntityBase> and gives a GenericRenderer<? extends EntityBase> GenericRenderer<? extends EntityBase> . Inside the GenericRenderer<? extends EntityBase> GenericRenderer<? extends EntityBase> , there's a method called draw that takes a SpriteBatch and an object that extends EntityBase (since the GenericRenderer is holding <? extends EntityBase> as the generic).

I'm using the map to hold the renderers for all of my entities, but when I call the draw method, Eclipse shows this error:

The method draw(SpriteBatch, capture#3-of ? extends EntityBase) in the type GenericRenderer is not applicable for the arguments (SpriteBatch, capture#4-of ? extends EntityBase)

Here is the code I use to iterate through my entities, cast them to EntityBase, grab their renderer, and run them through it:

for(Entity entity : gameStage.getEntityEngine().getEntities()) {
    if(entity instanceof EntityBase) {
         EntityBase entityBase = (EntityBase) entity;

         GenericRenderer<? extends EntityBase> renderer = 
                 Betley.instance.renderer.getRenderer(entityBase.getClass());

         renderer.draw(batch, entityBase.getClass().cast(entityBase));
    }
}

The ? extends EntityBase ? extends EntityBase means that it might be restricted to a subtype, but you don't know what subtype. That means the compiler can't be sure that the object you're passing is actually of the correct type.

Imagine that you have a pair of classes named Foo and Bar that both extend EntityBase . If your renderer variable is a GenericRenderer<? extends EntityBase> GenericRenderer<? extends EntityBase> , that means the object it refers to could be a GenericRenderer<Foo> , or it could be a GenericRenderer<Bar> . The compiler doesn't know which, and it could vary from entity to entity.

So when you call draw , you've cast your entityBase reference to a specific type like Foo or Bar , but the compiler can't determine that it's the right class. You might be trying to pass a Foo to a renderer that's actually a Renderer<Bar> , or vice versa. That's why you get the error. ? extends EntityBase ? extends EntityBase doesn't mean "accepts any subclass of EntityBase ", it means "might be restricted to a single subclass that we don't know".

I suspect your basic design isn't really compatible with how Java's generics work: if you have a Map whose values are GenericRenderer<? extends EntityBase> GenericRenderer<? extends EntityBase> , that means you plan to have some values that are GenericRenderer<Foo> , some that are GenericRenderer<Bar> , and so on. But there's no information available at compile time about which type of entity each renderer needs, so the compiler can't check that you're passing the correct type of entity to each renderer.

You might need to change your map's value type to GenericRenderer<EntityBase> and put a cast in each renderer's draw method to check (at runtime) that the correct type of entity was passed. Alternatively, come up with a design that doesn't involve mixing different types of renderers in a single collection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM