由于这个问题被标记为“Java”,我假设这个问题是关于Java中的FP实践(即不可变性)。
如今在Java中的良好实践是使用构建器:
Employee e = Employee.builder()
.surname("Lex")
.age(24)
.name("Vasili")
.salary(2500)
.build();
或者是静态构造函数:
Employee e = Employee.of("Vasili", "Lex", 24, 2500);
在这两种情况下,“经典”构造函数应该被声明为私有的,以确保对象不能被实例化并在不一致的状态下对客户端可用。
然后,对象变异器应该返回新对象:
Employee.of("Vasili", "Lex", 24, 2500) // creates an object
.updateName("Sergey") // returns 1st modified copy
.updateSalary(3500); // returns 2nd modified copy based on 1st copy
遵循这些实践,通常不需要非最终本地引用。
一个非常流行的例子是日期和时间API。
现在,关于使用可变的本地变量。那没问题,但是可以通过方法链缩短代码并使其更具表现力。尝试直接链接静态方法将不会看起来很优雅:
Employee e = setSalary(setAge(setName(new Employee("Lex", 24, 250), "Vasili"), 12), 2500);
为了模拟一个单子,可以将对象包装在类似单子的容器中,该容器定义了一个bind方法,该方法接受一个函数,该函数将接受存储在单子中的对象并返回一些结果,该结果将再次被包装在单子中。一个简单的例子如下:
static class Employee {
public String name;
public int age;
public long salary;
}
static class Monad<T> {
private final T value;
private Monad(T value) { this.value = value; }
public static <T> Monad<T> of(T value) {
return new Monad<>(value);
}
public T getValue() { return value; }
public Monad<T> bind(UnaryOperator<T> operator){
return of(operator.apply(value));
}
}
public static void main(String[] args) {
Employee value = Monad.of(new Employee())
.bind(e -> {e.name = "Lex"; return e; })
.bind(e -> {e.age = 24; return e; })
.bind(e -> {e.salary = 2500; return e; })
.getValue();
}
但是从Java 8开始,这可以通过核心Java来完成 - Stream API 可以完成这项任务以及更多的功能:
Stream.of(new Employee())
.map(e -> {e.name = "Lex"; return e; })
.map(e -> {e.age = 24; return e; })
.map(e -> {e.salary = 2500; return e; })
.findFirst()
.get();
final
。参数也是如此。 - Andreasnew Employee("Lex", 24, 250).withName("Vasili").withAge(12).withSalary(2500)
,其中每个with
方法都返回一个新的Employee
对象。 - Louis Wassermanfinal
,以便它们不能被重新分配/更新/修改。 - Andreas