回调到类(非实例)

时间:2015-02-06 15:59:49

标签: java oop callback lwjgl

LWJGL 3使用回调系统来处理输入,如下所示:

public class Main
{

    ...

    public static void main(String[] args)
    {
        glfwSetKeyCallback(window, keyCallback = new GLFWKeyCallback()
        {
            @Override
            public void invoke(long window, int key, int scancode, int action, int mods)
            {

            }
        });
    }

}

但是,我不希望在代码中间处理我的输入以用于其他目的。

我可以使用GLFWKeyCallback扩展一个类,并将该类的实例传递给glfwSetKeyCallback(),但是我没有在实例中执行该函数。它从静态函数(main)运行。我不希望将代码从main转移到一个实例对象,因为它与我的编码风格冲突,这会让我感到压力,最终我会陷入困境并将其撤消。

我现在的方式是这样的:

public class Main
{

    private static GLFWKeyCallbackProxy glfwKeyCallbackProxy;

    public static void main(String[] args)
    {
        glfwSetKeyCallback(window, glfwKeyCallbackProxy);
    }

}

public class GLFWKeyCallbackProxy extends GLFWKeyCallback
{

    @Override
    public void invoke(long window, int key, int scancode, int action, int mods)
    {
        // Communicate back to Main
    }

}

我真的不喜欢这个,因为GLFWKeyCallbackProxy现在正在实现游戏的一部分,而不仅仅是游戏使用。我认为它对抗良好的OOP结构,并且具有紧密耦合。

理想情况下,我的解决方案希望在某种程度上等同于这个假设的代码:

public class Main extends GLFWKeyCallback
{

    public static void main(String[] args)
    {
        glfwSetKeyCallback(window, ???);
    }

    @Override
    public static void invoke(long window, int key, int scancode, int action, int mods)
    {
        // This function now resides along side the code dealing with the rest of the game.
    }

}

基本上我希望回调函数将静态类级别函数视为一个实例,即使它不是。

你将如何实现这一目标,或者我是否必须采用与上述解决方案相似的紧密耦合?

编辑:我忘了提及,无论如何,我都需要访问GLFWKeyCallback的内部。让我们假设我不能纯粹通过引用(通过公共或getter / setter)访问这些内部。

解决方案我最终采取了:

public class Game
{
    static long window;

    public static void keyboardInvoke(long window, int key, int scancode, int action, int mods)
    {

    }

    public static void mouseInvoke(long window, int button, int action, int mods)
    {

    }

    public static void main(String[] args)
    {
        glfwSetKeyCallback(window, GLFWKeyCallback(Game::keyboardInvoke));
        glfwSetMouseButtonCallback(window, GLFWMouseButtonCallback(Game::mouseInvoke));
    }

}

1 个答案:

答案 0 :(得分:0)

我的第一个建议是开始使用"在代码中间处理我的输入以用于其他目的"。

现在,如果你真的不想这样做,那么你可以试试这个:

public class Main
{
    public static void main(String[] args)
    {
        glfwSetKeyCallback(window, new GLFWKeyCallbackProxy());
    }

    class GLFWKeyCallbackProxy extends GLFWKeyCallback
    {
        @Override
        public void invoke(long window, int key, int scancode, int action, int mods)
        {
            // Communicate back to Main
        }
    }
}

你的内部类可以访问包含类的成员,所以你应该没问题。

但我强烈建议你考虑的建议是继续使用Java 8,在那里你可以做到这样的事情:

public class Main
{
    public static void main(String[] args)
    {
        glfwSetKeyCallback( window, Main::invoke );
    }

    void invoke(long window, int key, int scancode, int action, int mods)
    {
        // Communicate back to Main
    }
}

...所以invoke()成为Main的成员方法,一切都很美。

此外,一个最终建议,与手头的问题无关:永远不要在静态main()中写任何重要的代码。 main()应该做的第一个(也是唯一的)事情是实例化一个对象并将控制传递给它。