Как сделать так, чтобы потребитель более точного типа передавался как потребитель менее точного типа?
У меня есть следующие два функциональных интерфейса:
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
ожидается.