java – 整个程序可以是不可变的吗?

>我熟悉不变性,可以设计不可变的课程,但我主要是学术知识,缺乏经验

>请参考上面的链接图片(不允许嵌入)

>从下往上看

>学生需要一个新地址

>我们创建了一个包含新地址的新学生,而不是真正改变学生

> mutator方法返回此新对象

问题:假设mutator调用来自一个不可变对象,这个新对象怎么办?

>新学生不能保存在讲座中,因为讲座也是不可改变的
>因此,我们需要一个新的讲座,其中包含新的学生
>但是在哪里保存新的讲座?
>当然,在一个新的学期,但它在哪里结束?
>至少可以通过使用组件外观模式来破坏链,该模式处理所有新对象的创建,而无需通过整个链转发调用

问题:这在哪里停止?是不是必须有一个可变对象,至少保存最顶层的实例?

最佳答案 这是函数式编程的概念.一切都是不可变的,不允许函数调用产生副作用.修改复杂对象的唯一方法是重新创建父对象,就像在您的示例中一样.

现在的问题是如何改变程序状态.因此,我们首先考虑堆栈.它包含所有局部变量的值以及被调用函数的所有参数的值.我们可以通过调用新函数来创建新值.我们可以通过从函数返回来丢弃值.因此,我们可以通过调用函数来改变程序状态.但是,并不总是可以从函数返回以丢弃其局部变量,因为我们可能只想丢弃一些局部变量,但需要保留其他变量的值以进行进一步的操作.在这种情况下,我们根本无法返回,但我们需要调用另一个函数并仅将一些局部变量传递给它.现在,为了防止堆栈溢出,函数式语言有一个称为尾调用优化的功能,它可以从调用堆栈中删除不必要的条目.如果要为相关函数做的唯一事情是返回自己调用的函数的值,则不需要调用堆栈的条目.在这种情况下,保持调用堆栈条目没有意义.通过删除不必要的调用堆栈条目,丢弃否则未使用的局部变量的值.您可能想要阅读它here.此外,tail recursion与此相关.

同样,这是纯函数式编程语言的概念,如Haskell.真的很好,一切都是不可变的,但是这些语言有他们唯一的问题和他们自己的方法来处理这些.例如,Monads(以及更高级的kinded类型)可用于这些语言,但在命令式/面向对象的编程语言中很少见到.

我喜欢在程序存储器的叶子上有不可变的值.但是,组成这些不可变值的代码实际上构成了应用程序逻辑,它确实包含可变状态.对我而言,这结合了两个世界的优势.然而,这似乎是一个偏好的问题.

点赞