0

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
  • 2,841
  • 3
  • 22
  • 32
  • State.selectAction(state.getActions(), selector) – Crammeur Nov 09 '17 at 00:02
  • What do you mean by "incompatible types"? Please post the relevant error message here. Also show the definition for `ACTION` – smac89 Nov 09 '17 at 00:02
  • 2
    `.State, ACTION>` to make it compile, but this is ridiculous. Please find another way to model your use case, whatever it is. – Sotirios Delimanolis Nov 09 '17 at 00:04
  • The error was Incompatible types: Required: ACTION Found: Java.lang.Object – AaronF Nov 09 '17 at 00:05
  • In your first version, couldn't you simply use `State state`, and drop the `STATE` type variable altogether? – Andy Turner Nov 09 '17 at 00:05
  • public ACTION searchAction(State state, int selector) has the same error. And I realize it is ridiculous. I'm trying to understand Generics better, and trying to figure out why it doesn't work, not why it's terrible. Thanks. – AaronF Nov 09 '17 at 00:07

1 Answers1

0

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
  • 137,514
  • 11
  • 162
  • 243