Я создаю свободный API, который примерно работает следующим образом (предполагается, что существует класс Person
с геттером getId
, который возвращает Long
):
String result = context.map(Person::getId)
.pipe(Object::toString)
.pipe(String::toUpperCase)
.end(Function.identity())
Как видите, только функция .end
действует как оператор терминала. Это мешает общему использованию указанного API, так как мне часто приходится заканчивать .end(Function.identity())
-колл, даже если предыдущий .pipe
-колл уже имеет правильный тип.
Есть ли способ создать свободный API, позволяющий его части быть одновременно оператором терминала и «оператором моста»? Я просто не хочу загромождать API специализированными pipe
-вариантами, такими как pipeTo
(канал, который принимает только Function<CurrentType, ExpectedType>
и внутренне вызывает .end
), эмулирующим указанное поведение, так как он заставляет пользователя думать о очень определенная часть API, которая мне кажется ненужной.
EDIT:
Упрощенная реализация контекста по запросу:
class Context<InType, CurrentType, TargetType> {
private final Function<InType, CurrentType> getter;
public Context(Function<InType, CurrentType> getter) {
this.getter = getter;
}
public <IntermediateType> Context<InType, IntermediateType, TargetType>
pipe(Function<CurrentType, IntermediateType> mapper) {
return new Context<>(getter.andThen(mapper));
}
public Function<InType, TargetType> end(Function<CurrentType, TargetType> mapper) {
return getter.andThen(mapper);
}
}
//usage
Function<Person, String> mapper = new Context<Person, Long, String>(Person::getId)
.pipe(Object::toString)
.pipe(String::toUpperCase)
.end(Function.identity());
mapper.apply(new Person(...))