问题标签 [immutability]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
8 回答
2290 浏览

functional-programming - 高度可变域中的不可变功能对象

我目前正在利用 Scala 的业余时间学习函数式编程,并且我有一个空闲的新手问题。

在执行诸如计算 Haar 小波变换之类的操作时,我可以看到拥有不可变对象的优雅——即当由对象表示的数据本身没有改变时。

但是我看到一个博客,其中有人在演示不变性时以一个小游戏为例。如果一个生物对象受到伤害,它不会改变它的状态——它返回一个具有新生命值和一个新的“仇恨 X”标志的新生物对象。但如果我们要设计类似 MMORPG 的东西,魔兽世界会这样说。一百名玩家在战场上……可能有数千种攻击和增益/减益法术效果以不同的方式影响他们。是否仍然可以用完全不可变的对象来设计系统?在我看来,每个“滴答”都会有一大群新实例。为了获得当前有效的对象实例,所有客户端都必须不断地通过某种中央“游戏世界”对象,或者?

函数式编程是否适用于此,或者这是“最好的工作的最佳工具,在这里可能不是一成不变的”?

0 投票
15 回答
26214 浏览

java - 如何在 Java 中识别不可变对象

在我的代码中,我正在创建一个对象集合,这些对象将由各种线程以一种仅在对象不可变时才安全的方式访问。当尝试将新对象插入我的集合时,我想测试它是否是不可变的(如果不是,我将抛出异常)。

我可以做的一件事是检查一些众所周知的不可变类型:

这实际上让我完成了 90% 的工作,但有时我的用户会想要创建自己的简单不可变类型:

有什么方法(可能使用反射)可以可靠地检测一个类是否是不可变的?误报(认为它不可变时认为它是不可变的)是不可接受的,但误报(认为它不可变时认为它是可变的)是不可接受的。

编辑添加:感谢您提供有见地和有用的答案。正如一些答案所指出的,我忽略了定义我的安全目标。这里的威胁是无知的开发人员——这是一段框架代码,将被大量对线程几乎一无所知并且不会阅读文档的人使用。我不需要防御恶意开发者——任何足够聪明地改变字符串或执行其他恶作剧的人也将足够聪明地知道在这种情况下它是不安全的。代码库的静态分析是一种选择,只要它是自动化的,但不能指望代码审查,因为不能保证每个审查都会有精通线程的审查者。

0 投票
9 回答
17686 浏览

c# - .NET 中是否可以使用不可变数组?

是否有可能以某种方式将 a 标记System.Array为不可变。当放在 public-get/private-set 后面时,它们不能被添加,因为它需要重新分配和重新分配,但消费者仍然可以设置他们希望的任何下标:

我认为readonly关键字可能会起作用,但没有这样的运气。

0 投票
12 回答
96338 浏览

oop - 可变对象与不可变对象

我试图了解可变对象与不可变对象。使用可变对象会带来很多负面影响(例如,从方法中返回字符串数组),但我无法理解这样做的负面影响。使用可变对象的最佳实践是什么?你应该尽可能避免它们吗?

0 投票
15 回答
19224 浏览

c# - C# 中的不可变对象模式 - 你怎么看?

在几个项目的过程中,我开发了一种用于创建不可变(只读)对象和不可变对象图的模式。不可变对象具有 100% 线程安全的优点,因此可以跨线程重用。在我的工作中,我经常在 Web 应用程序中将这种模式用于配置设置以及我在内存中加载和缓存的其他对象。缓存对象应该始终是不可变的,因为您希望确保它们不会被意外更改。

现在,您当然可以轻松地设计不可变对象,如下例所示:

这对于简单的类来说很好——但对于更复杂的类,我不喜欢通过构造函数传递所有值的概念。在属性上有设置器更可取,并且构建新对象的代码更易于阅读。

那么如何使用 setter 创建不可变对象呢?

好吧,在我的模式中,对象一开始是完全可变的,直到你用一个方法调用冻结它们。一旦一个对象被冻结,它将永远保持不可变——它不能再次变成一个可变对象。如果您需要对象的可变版本,您只需克隆它。

好的,现在开始一些代码。我在以下代码片段中尝试将模式归结为最简单的形式。IElement 是所有不可变对象最终必须实现的基本接口。

Element 类是 IElement 接口的默认实现:

让我们重构上面的 SampleElement 类来实现不可变对象模式:

您现在可以通过调用 MakeReadOnly() 方法更改 Id 属性和 Name 属性,只要该对象未被标记为不可变。一旦它是不可变的,调用 setter 将产生 ImmutableElementException。

最后说明:完整模式比此处显示的代码片段更复杂。它还包含对不可变对象集合和不可变对象图的完整对象图的支持。完整模式使您可以通过调用最外层对象的 MakeReadOnly() 方法将整个对象图变为不可变。一旦开始使用这种模式创建更大的对象模型,泄漏对象的风险就会增加。泄漏对象是在对对象进行更改之前未能调用 FailIfImmutable() 方法的对象。为了测试泄漏,我还开发了一个用于单元测试的通用泄漏检测器类。它使用反射来测试是否所有属性和方法都将 ImmutableElementException 抛出为不可变状态。换句话说,这里使用了 TDD。

我已经非常喜欢这种模式,并从中发现了巨大的好处。所以我想知道的是你们中是否有人使用类似的模式?如果是,您是否知道任何记录它的好资源?我本质上是在寻找潜在的改进以及在这个主题上可能已经存在的任何标准。

0 投票
17 回答
184804 浏览

java - 不可变是什么意思?

这可能是有史以来最愚蠢的问题,但我认为这对于 Java 新手来说是相当混乱的。

  1. 有人可以澄清什么是不可变的吗?
  2. 为什么是String不可变的?
  3. 不可变对象的优点/缺点是什么?
  4. 为什么像 String 这样的可变对象StringBuilder应该优先于 String ,反之亦然?

一个很好的例子(在Java中)将不胜感激。

0 投票
3 回答
2772 浏览

data-structures - 关系数据库的高效持久数据结构

我正在寻找可用于实现关系模型的持久数据结构的材料。

不可变数据结构含义的持久性。

有人知道一些好的资源、书籍、论文等吗?

(我已经有书Purely Functional Data Structures,这是我正在寻找的一个很好的例子。)

0 投票
3 回答
3194 浏览

concurrency - Java中的不可变bean

我很好奇为 java bean 提供不变性的可能性(这里的 bean 是指具有为成员提供 getter 和 setter 的空构造函数的类)。显然,这些类不是不可变的,它们用于从数据层传输值,这似乎是一个真正的问题。

StackOverflow 中提到了一种解决此问题的方法,称为“C# 中的不可变对象模式”,其中对象在完全构建后被冻结。我有另一种方法,真的很想听听人们对此的看法。

该模式涉及两个类 Immutable 和 Mutable,其中 Mutable 和 Immutable 都实现了一个提供非可变 bean 方法的接口。

例如

这种方法允许使用反射(通过通常的约定)构建 bean,并且还允许我们在最近的机会转换为不可变的变体。不幸的是,每个 bean 显然有大量的样板。

我很想听听其他人对这个问题的看法。(我很抱歉没有提供一个好的问题,可以回答而不是讨论:)

0 投票
8 回答
56952 浏览

c# - 如何创建不可变类?

我正在创建一个不可变的类。
我已将所有属性标记为只读。

我有一个班级项目清单。
虽然如果属性是只读的,则可以修改列表。

公开列表的 IEnumerable 使其不可变。
我想知道使类不可变必须遵循的基本规则是什么?

0 投票
4 回答
3075 浏览

language-agnostic - 函数式编程:状态与重新分配

我需要帮助来了解我当前的 OOP 状态概念与使用 Haskell 或 Clojure 等函数式语言的方式之间的差异。

举一个陈腐的例子,假设我们正在处理简化的银行账户对象/结构/任何东西。在 OOP 语言中,我将有一些类持有对 BankAccount 的引用,该类将具有用于利率之类的实例变量,以及诸如 setInterestRate() 之类的方法,它们会更改对象的状态并且通常不返回任何内容。比如说 Clojure,我有一个银行账户结构(一个美化的哈希图),以及接受银行账户参数和其他信息并返回一个新结构的特殊函数。因此,我现在没有更改原始对象的状态,而是返回了一个带有所需修改的新对象。

那么......我该怎么办?覆盖引用旧银行帐户的任何变量?如果是这样,这是否比改变状态的 OOP 方法具有优势?最后,在这两种情况下,似乎都有一个变量引用了具有必要更改的对象。尽管我很迟钝,但我对正在发生的事情只有一个模糊的概念。

我希望这是有道理的,感谢您的帮助!