gpt4 book ai didi

scala - 何时在 Scala 中使用可变类和不可变类

转载 作者:行者123 更新时间:2023-12-04 01:54:25 25 4
gpt4 key购买 nike

有很多关于不可变状态的优点的文章,但是在 Scala 中是否存在偏好可变类的常见情况? (这是一个 Scala 新手问题,来自具有使用可变类的“经典”OOP 设计背景的人。)

对于像 3 维 Point 类这样的微不足道的东西,我得到了不变性的优势。但是,像 Motor 类这样公开各种控制变量和/或传感器读数的东西呢?经验丰富的 Scala 开发人员通常会编写这样一个不可变的类吗?在这种情况下,“speed”是否会在内部表示为“val”而不是“var”,并且“setSpeed”方法会返回该类的新实例?类似地,来自描述电机内部状态的传感器的每个新读数是否都会导致实例化一个新的 Motor 实例?

在 Java 或 C# 中使用类封装可变状态的“旧方法”似乎非常适合 Motor 示例。所以我很想知道,一旦您获得了使用不可变状态范式的经验,您是否甚至会设计一个像 Motor 这样的不可变类。

最佳答案

我将使用一个不同的经典 OO 建模示例:银行账户。

这些几乎用在地球上的每一个面向对象的类(class)中,你通常最终得到的设计是这样的:

class Account(var balance: BigDecimal) {
def transfer(amount: BigDecimal, to: Account): Unit = {
balance -= amount
to.balance += amount
}
}

IOW:余额是数据,转账是操作。 (还要注意,传输是一个复杂的操作,涉及多个可变对象,但是它应该是原子的,而不是复杂的……所以你需要锁定等。)

然而,这是错误的。这不是银行系统的实际设计方式。事实上,这也不是真实世界(实体)银行业务的运作方式。实际的实体银行和实际的银行系统是这样工作的:
class Account(implicit transactionLog: TransactionLog) {
def balance = transactionLog.reduceLeft(_ + _)
}

class TransactionSlip(from: Account, to: Account, amount: BigDecimal)

IOW:余额是操作,传输是数据。请注意,这里的一切都是不可变的。余额只是交易日志的左侧折叠。

另请注意,我们甚至没有将纯粹的功能性、不可变设计作为明确的设计目标。我们只是想对银行系统进行正确建模,但巧合的是,我们最终得到了一个纯粹的功能性、不可变的设计。 (嗯,这实际上并非巧合。现实世界中的银行业务以这种方式工作是有原因的,它具有与编程相同的好处:可变状态和副作用使系统变得复杂和困惑……而在银行业务中,这意味着钱不见了。)

这里的重点是完全相同的问题可以用非常不同的方式建模,并且根据模型,您可能会想出一些微不足道的东西,使其完全不可变或非常困难。

关于scala - 何时在 Scala 中使用可变类和不可变类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19085392/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com