Вопрос:

Java Generic extends subclass Incompatible types

java generics abstract-class inner-classes

503 просмотра

1 ответ

858 Репутация автора

First, I've looked at a lot of previous posts, including:

Java Generics and generic types

Java generics incompatible type

Java Generics Incompatible Types

Java generics: incompatible types

None of them address the issue I'm having. The following code is somewhat contrived, but illustrates the problem. I'm using Java 1.8.

import java.util.List;

/**
 * Created by aaron on 11/8/2017.
 */
public abstract class Selecter<STATE extends Selecter.State, ACTION> {
    public abstract class State {
        public abstract List<ACTION> getActions();
        public abstract ACTION selectAction(List<ACTION> list, int selector);
    }

    public ACTION searchAction(STATE state, int selector) {
        return state.selectAction(state.getActions(), selector);
    }
}

Now, since STATE must be a Selector.State, and getActions() returns a List<ACTION> and selectAction() returns an ACTION from a List<ACTION>, why is there an incompatible types error in searchAction()?

How can I fix it?

EDIT

I think I've fixed it:

import java.util.List;

/**
 * Created by aaron on 11/8/2017.
 */
public abstract class Selecter<ACTION> {
    public abstract class State<A> {
        public abstract List<A> getActions();
        public abstract A selectAction(List<A> list, int selector);
    }

    public ACTION searchAction(State<ACTION> state, int selector) {
        return state.selectAction(state.getActions(), selector);
    }
}

However, I don't know why this works and the other doesn't.

Автор: AaronF Источник Размещён: 08.11.2017 11:59

Ответы (1)


0 плюса

96318 Репутация автора

Your original attempt doesn't work because you're using raw types.

class Selecter<STATE extends Selecter.State, ACTION>
                              ^ Selecter is generic, missing type variables.

As such, if you try to use a STATE, the generics are erased. So in:

public ACTION searchAction(STATE state, int selector) {
    return state.selectAction(state.getActions(), selector);
}

the return value is of type Object, not ACTION, because that's the upper bound of ACTION.

You could add the type variables, as suggested by Sotirios:

class Selecter<STATE extends Selecter<STATE, ACTION>.State, ACTION>

but that is pretty messy.

State is an inner class of Selecter, so it inherits its type variables. As such:

public abstract class Selecter<ACTION> {
    public abstract class State {
        public abstract List<ACTION> getActions();
        public abstract ACTION selectAction(List<ACTION> list, int selector);
    }

    public ACTION searchAction(State state, int selector) {
        return state.selectAction(state.getActions(), selector);
    }
}

seems like the easiest solution. This compiles fine.

Автор: Andy Turner Размещён: 09.11.2017 12:07
Вопросы из категории :
32x32