Функциональное программирование на Java 8 - необходимо написать универсальную функцию для класса - PullRequest
3 голосов
/ 07 марта 2019

Я хочу создать метод, который принимает что-то вроде этого

set(nodeStatus, status, NodeStatus::setStatus, Status::valueOf);
set(nodeStatus, errorCode, NodeStatus::setErrorCode, ErrorCode::valueOf);

Status и ErrorCode - это перечисления в java.

Подпись и псевдокод

set(NodeStatus nodeStatus, byte[] status, ?nodeStatusOperator , ?ValueTransformer) {
   1. convert byte[] status to appropriate value as per ValueTransformer
   2. nodeStatusOperator sets this transformed value according to the lambda passed.
}

Я хочу знать, какую сигнатуру метода следует использовать для достижения этой цели в Java и почему. Я пробовал разные потребители, биконсьюмеры и т. Д., Но не смог этого сделать. Может кто-нибудь помочь, пожалуйста?

Ответы [ 2 ]

4 голосов
/ 07 марта 2019

Насколько я могу судить, вам нужно вот что:

public <T> void set (NodeStatus nodeStatus, 
                     byte [] value, 
                     BiConsumer<NodeStatus,T> setter, 
                     Function<byte[],T> transformer) {
    T transformedValue = transformer.apply(value);
    setter.accept(nodeStatus, transformedValue);
}

(Если value может отличаться от byte[], его можно заменить другим параметром типа.)

Ps: setter - это BiConsumer, потому что вы используете статическую ссылку на метод (например, NodeStatus::setErrorCode) на метод экземпляра, поэтому первый аргумент BiConsumer должен быть NodeStatus instance setErrorCode() будет вызван.

P.p.s: Как указывает glglgl , вы потенциально можете упростить свой код до этого:

public <T> void set (byte [] value, 
                     Consumer<T> setter, 
                     Function<byte[],T> transformer) {
    T transformedValue = transformer.apply(value);
    setter.accept(transformedValue);
}

И назовите это так:

set(status, nodeStatus::setStatus, Status::valueOf);

... где nodeStatus - это экземпляр NodeStatus, которым вы хотите манипулировать.

0 голосов
/ 07 марта 2019

Немного неясно, чего вы пытаетесь достичь. Зачем передавать NodeStatus и функцию, если вы можете просто передать функцию, которая работает с этим конкретным экземпляром NodeStatus, например ::

static <T> void set(byte[] status, Consumer<T> nodeStatusOperator, Function<String, T> transformer) {
    nodeStatusOperator.accept(transformer.apply(new String(status)));
}

public static void main(String[] args) {
    NodeStatus nodeStatus = new NodeStatus();
    byte[] status = new byte[0];
    set(status, nodeStatus::setStatus, Status::valueOf);
    set(status, nodeStatus::setErrorCode, ErrorCode::valueOf);
}

И что эта щедрость дает вам более простой подход?

nodeStatus.setStatus(Status.valueOf(new String(status)));
nodeStatus.setErrorCode(ErrorCode.valueOf(new String(status)));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...