Associated template in a common field

For example, I have these general classes:

class Base<A, B extends Base<?, B>> {}
class SubA extends Base<String, SubA> {} // B = own type
class SubB extends Base<String, SubB> {} // B = own type
class SubC extends Base<String, SubA> {} // B != own type

Here the problem arises: how to store (as a field / class variable) a list of a particular subclass of objects Base, so that the type Bis the type of the subclass (i.e., allow only List<SubA>or List<SubB>not List<SubC>)?

Method Equivalent:

public <T extends Base<?, T>> List<T> getList() {}

However, there is no way to declare a variable with this T. How can I fix this?

Edit

(Editing 2: I fixed the code examples because I made some mistakes when writing those that don't have an IDE)

After reading Andy's comment, I think this example is not very accurate to express the problem that I am facing. I will give a more accurate example (although the example may not look like a reasonable idea).

abstract class Wrapper<T, W extends Wrapper<T, W>> {
    public abstract W wrap(T original);
    public abstract T unwrap(W wrapper);
}
abstract class NumberWrapper<T extends Number, W extends NumberWrapper<T, W> extends Wrapper<T, W> {
    public final Number getNumber() {
        return unwrap();
    }
}
class IntegerWrapper extends NumberWrapper<Integer, IntegerWrapper> {}
class DoubleWrapper extends NumberWrapper<Double, DoubleWrapper> {}
class LongWrapper extends NumberWrapper<Long, LongWrapper> {}

abstract class ValuePrinter<T> {
    public abstract void printValue(T value);
}

class Foo {
    private ValuePrinter<NumberWrapper<?, ?>> printer = new ValuePrinter<NumberWrapper<?, ?>>() {
        @Override public void printValue(NumberWrapper<?, ?> value) {
            Number num = value.getNumber();
            System.out.println(num); // Don't ask why this is done
        }
    };

    public ValuePrinter<NumberWrapper<?, ?>> getPrinter() { return printer; }
}

/**
 * A scheduler that prints value once every 5 seconds.
 */
static class Scheduler<T> {
    private LinkedList<T> printingQueue;
    private final ValuePrinter<T> printer;

    public Scheduler(ValuePrinter<T> printer) {
        this.printer = printer;
    }

    public void scheduleToPrint(List<T> toPrint) {
        printingQueue.addAll(toPrint);
        startIfNotStarted();
    }
}

class Test {
    private List<DoubleWrapper> doubleWrappers;
    private List<IntegerWrapper> intWrappers;
    private Foo foo;

    public void scheduledPrintDoubles() {
        new Scheduler<>().scheduleToPrint(doubleWrappers, foo.getPrinter()); // Compile error
    }
}

, , . printer ValuePrinter<NumberWrapper<?, ?>>, .

Scheduler.getInstance().scheduleToPrint(w, Foo::printValue) , , w , , Foo::printValue, DoubleWrapper ( NumberWrapper<?, ? extends NumberWrapper>) NumberWrapper<?, ?> T, scheduleToPrint.

, IDE Eclipse:

The method scheduleToPrint(List<NumberWrapper<?,?>>) in the type 
Scheduler<NumberWrapper<?,?>> is not applicable for the arguments 
(List<DoubleWrapper>)
+4

Source: https://habr.com/ru/post/1695451/


All Articles