java - 将命令式 Java 转换为函数式 Java(游戏)

标签 java functional-programming java-8 imperative-programming declarative-programming

我正在学习更多关于 Java 8 及其功能的知识,我想用它做更多的练习。比方说,我有以下命令式代码,用于在屏幕边界周围环绕一个圆圈:

if (circle.getPosition().getX() > width + circle.getRadius()){
    circle.getPosition().setX(-circle.getRadius());
}else if (circle.getPosition().getX() < -circle.getRadius()){
    circle.getPosition().setX(width + circle.getRadius());
}
if (circle.getPosition().getY() > height + circle.getRadius()){
    circle.getPosition().setY(-circle.getRadius());
}else if (circle.getPosition().getY() < -circle.getRadius()){
    circle.getPosition().setY(height + circle.getRadius());
}
  1. 我怎样才能着手尝试“功能化”它?也许一些伪代码?在我看来,可变性和状态似乎是这个例子中固有的。
  2. 函数式编程不适合游戏开发吗?我喜欢两者,所以我尝试将它们结合起来。

最佳答案

在此示例中,对可变性的要求没有任何固有的要求。必要的方法是通过应用改变现有圈子状态的副作用来修改现有圈子。

函数式方法是拥有一个不可变的数据结构,并创建一个从第一个结构中获取数据并创建一个新结构的函数。在您的示例中,函数式方法会使圆圈不可变,即没有 setX() 或 setY() 方法。

private Circle wrapCircleAroundBounds(Circle circle, double width, double height) {
    double newx = (circle.getPosition().getX() > width + circle.getRadius()) ? -circle.getRadius() : width + circle.getRadius()
    double newy = (circle.getPosition().getY() > height + circle.getRadius()) ? -circle.getRadius() : height + circle.getRadius()
    return new Circle(newx, newy)
}

使用 Java8 的函数式特性,您可以想象将圆列表映射到环绕的圆:

circles.stream().map(circ -> wrapCircleAroundBounds(circ, width, height))

命令式方法和函数式方法具有不同的优点,例如,函数式方法由于不可变性而本质上是线程安全的,因此您应该能够更轻松地并行化此类代码。例如,可以同样安全地写:

circles.parallelStream().map(circ -> wrapCircleAroundBounds(circ, width, height))

我不认为函数式编程一定不适合游戏开发,但尽管它已经完成,但它肯定不是标准方法,因此如果您使用函数式语言。

正如 dfeuer 在他的回答中所说,Java 的函数式特性非常原始——您不支持代数数据类型、模式匹配等,这将使以函数式风格表达问题变得容易得多(至少一旦您习惯那些成语)。我同意至少阅读一些关于 Haskell 的内容,它有一个很好的教程:http://learnyouahaskell.com/chapters将是一个很好的入门方式。与 Scala 不同,Scala 是一种非常多范式的语言,在学习新风格时,您不会有 OOP 功能可以依赖。

关于java - 将命令式 Java 转换为函数式 Java(游戏),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33058625/

相关文章:

java-8 - vavr中的流生成器​​方法

java - java中如何实现国际化

java - 在Java中查找数组中的多个搜索结果

Haskell:如何编写函数 "backwards",例如 Clojure 的线程 (->)?

c++ - 消除 C++ 中多余的模板参数

java - java 10中的Lazy flatMap实现算法

Java 8 将对象添加到列表的有效方法

java - 有没有更好的方法可以使用 Stream 进行编写?

java - 如何使用 Hibernate 逆向工程扩展父类(super class)以具有通用的 getter/setter

java - android Button.getWidth() 返回值 0