Как сделать так, чтобы потребитель более точного типа передавался как потребитель менее точного типа?

У меня есть следующие два функциональных интерфейса:

IndexBytePairConsumer.java

package me.theeninja.nativearrays.core;

@FunctionalInterface
public interface IndexBytePairConsumer {
    void accept(long index, byte value);
}

IndexIntPairConsumer.java

package me.theeninja.nativearrays.core;

@FunctionalInterface
public interface IndexIntPairConsumer {
    void accept(long index, int value);
}

У меня также есть следующий метод:

public void forEachIndexValuePair(IndexBytePairConsumer indexValuePairConsumer) {
    ...
}

Есть ли способ, которым я могу позволить IndexIntPairConsumer быть переданным в вышеупомянутом методе (так как потребитель целых чисел может принять байты)? Мне нужно использовать примитивы в сигнатурах методов, а не в связанных классах, таких как Integer а также Byte Таким образом, любая абстракция становится намного сложнее.

2 ответа

Вот что я изобрел для тебя.

определять

public interface IndexBytePairConsumer {
    void accept(long index, byte value);
}

public interface IndexIntPairConsumer extends IndexBytePairConsumer {
    default void accept(long index, byte value) {
        this.accept(index, (int) value);
    }

    void accept(long index, int value);
}

и вы можете использовать его

IndexIntPairConsumer c = (a,b)->{
    System.out.println(a + b);
};
forEachIndexValuePair(c);

forEachIndexValuePair((a, b) -> {
    System.out.println(a + b);
});

Без изменения иерархии типов (например, способа, предложенного в этом ответе), шаг адаптации неизбежен, так как IndexBytePairConsumer а также IndexIntPairConsumer два разных типа. Наименьший шаг адаптации будет

// given
IndexIntPairConsumer consumer = …

// call as
forEachIndexValuePair(consumer::accept);

Как вы сказали в своем вопросе, потребитель int может принимать байты, поэтому accept метод IndexIntPairConsumer является допустимой целью для ссылки на метод, где IndexBytePairConsumer ожидается.

Другие вопросы по тегам