将功能接口的实现作为参数传递

Nea*_*erd 2 java java-8 functional-interface

函数式接口描述如下:

package models;

@FunctionalInterface
public interface EventReducer {
    void apply(Event event, GameState state);
}

Run Code Online (Sandbox Code Playgroud)

我在以下类中实现该接口:

package models.reducers;

import models.Event;
import models.EventReducer;
import models.GameState;
import models.events.MinionDeathEvent;

public class MinionDeath implements EventReducer {

    @Override
    public void apply(Event event, GameState state) {
        MinionDeathEvent deathEvent = (MinionDeathEvent)event;
        deathEvent.getPlayer().getBoard().remove(deathEvent.getMinion());
    }
}
Run Code Online (Sandbox Code Playgroud)

如何将实现作为参数传递?例如,

    private static final Map<EventType, EventReducer> ReducersMap = Map.ofEntries(
        entry(EventType.DEATH, MinionDeath::apply);
    );
Run Code Online (Sandbox Code Playgroud)

显然,MinionDeath::apply这不是一条路

Tur*_*g85 5

问题

在当前的解决方案中,我们尝试在没有类实例的情况下引用实例方法

entry(EventType.DEATH, MinionDeath::apply);
Run Code Online (Sandbox Code Playgroud)

运行时无法MinionDeath自行创建 的实例,主要是因为不能保证无参数构造函数存在(在这种特殊情况下存在,但并非每个类都有无参数构造函数)。

解决方案

解决该问题有多种可能性。这里是其中的一些:

  1. 创建 的实例MinionDeath,并将其作为参数传递。

    entry(EventType.DEATH, new MinionDeath());
    
    Run Code Online (Sandbox Code Playgroud)
  2. Lambda 表达式:这基本上是将 lambda 的实现MinionDeath直接内联到 lambda 中。

    entry(
        EventType.DEATH, 
        (event, state) -> ((MinionDeathEvent) event).getPlayer()
                .getBoard()
                .remove(deathEvent.getMinion()));
    
    Run Code Online (Sandbox Code Playgroud)
  3. 将 lambda 定义为静态方法,将其作为方法引用传递。

    public class Game { // The class name is an assumption of mine
    
        ...
    
        private static void processMonsterDeathEvent(Event event, GameState state) {
            MinionDeathEvent deathEvent = (MinionDeathEvent)event;
            deathEvent.getPlayer().getBoard().remove(deathEvent.getMinion());
        }
    
        private static final Map<EventType, EventReducer> ReducersMap = Map.ofEntries(
            entry(EventType.DEATH, Game::processMonsterDeathEvent)
        );
    
        ...
    }
    
    Run Code Online (Sandbox Code Playgroud)

    关于此解决方案的评论:这与原始解决方案不同,因为我们现在引用静态方法。我们还可以将方法更改applyMinionDeathbe static。在这种情况下,我们应该... implements EventRecorder从类定义中删除 ,因为不再需要它。