Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在Scala中创建全功能的不可变类?_Java_Scala_Copy_Prototype - Fatal编程技术网

Java 如何在Scala中创建全功能的不可变类?

Java 如何在Scala中创建全功能的不可变类?,java,scala,copy,prototype,Java,Scala,Copy,Prototype,我注意到Scala有case类。这些似乎是用于模式匹配的,但我喜欢用它们来实现这一点: val bankAccount1 = new BankAccount("Daniel", 100) val bankAccount2 = bankAccount1.copy(funds = 200) 现在“丹尼尔”有两个银行账户,一个是100美元,一个是200美元。但是当事情变得更复杂时,BankAccount需要被子类化,这是行不通的,因为case类不能扩展其他case类 我想要不可变的类,而不是可以扩展

我注意到Scala有case类。这些似乎是用于模式匹配的,但我喜欢用它们来实现这一点:

val bankAccount1 = new BankAccount("Daniel", 100)
val bankAccount2 = bankAccount1.copy(funds = 200)
现在“丹尼尔”有两个银行账户,一个是100美元,一个是200美元。但是当事情变得更复杂时,
BankAccount
需要被子类化,这是行不通的,因为case类不能扩展其他case类

我想要不可变的类,而不是可以扩展成更多不可变的类。就像我希望能够扩展
BankAccount
以拥有不可变的子类
SavingsBankAccount
CheckingBankAccount
。我不确定此时是否需要扩展/实现
Clonable
接口或定义自定义复制方法或类似的东西。我不想在课堂上放太多的样板


(如果可能的话),我如何在Scala中创建不可变的类,这些类可以被复制和子分类,并且不会过于混乱或冗长?

我认为在Scala中实现这一点的惯用方法是使用封装而不是继承。例如,您可以:

case class BankAccount(id: AccountId, customer: Customer)
case class SavingsBankAccount(account: BankAccount, line: SavingsLine)
通过这种方式,您将保持不变性和自动应用、不应用、等于、哈希代码和复制方法生成的良好特性


然而,如果您真的想使用继承,那么除了推出自己的定制解决方案之外,您别无选择。例如,实现一个trait
subassessablecaseclass
,它实现了helper方法,可以快速定义case类免费提供的方法。

想想你的
银行账户是否真的需要具体

我可以有一个不是储蓄或支票类型的银行账户吗

如果这个问题的答案是否定的(在这个例子中,我想是的),您可以使用一个抽象类或

特质

当你真的不需要层次结构时,你可以对特征做很多事情。实际上,traits比抽象类更好,因为您可以具有可组合性

我发现scala中的编程在大多数情况下不需要扩展具体对象,特别是只打包数据的类


如果你真的需要银行账户具体化,我想你只剩下你已经提出的建议了(

这是一个非常丑陋的解决方案,因为它不允许我在不改变具体对象介绍特征然后重构所有内容的情况下处理已经存在的代码。更新的答案。如果这不能解决您的问题,很抱歉:(.我从你的例子中看到,BankAccount让我认为这可能是一个抽象类/特征。我不知道你的重构代码。但是相信我,在Java中,我们习惯于依赖很多具体对象的扩展。现在我很少在scala中使用它。只有一件事:抽象类不能解决你的问题吗(没有太多重构?)我不知道你在重构:(,抱歉。但在编写新代码时,请尝试遵循这一点。无法扩展case类让我很恼火,但现在我很少需要它。封装似乎是一个更好的解决方案。读写非常干净,不需要大规模重构或过多的样板文件。Scala有办法代理acc中的所有公共方法和变量吗账户:银行账户转入“储蓄银行账户”?比如我可以让BankAccount扩展代理或类似的东西吗?我明白了。我可以使用implicit关键字将SavingsBankAccount.account委托给SavingsBankAccount类。比如:是的,您可以使用隐式转换对
SavingsBankAccount
进行操作,就像它是
BankAccount
一样。但是请尝试,不要尝试过度使用这个范例。隐式转换非常有用,而且非常方便,如果使用太多,它们会使代码难以理解,特别是对于第一次研究代码库的新团队成员。这可能很愚蠢,但我最终将所有具有父类子类的东西都变成了一个名为“Child”的通用抽象类然后将这些子类转发给子类中名为Child.parent的参数。Traits可用于需要重写的方法。有点混乱,但如下所示:从函数的、不可变的类继承的问题是它们不再是(保证是)函数式的,不可变的,因为子类可以重写其中一个方法以产生副作用。尝试使用静态类型检查解决此问题很棘手,基本上相当于解决停止问题。这就是我基本上解决此问题的方法:。我制作了一个隐式消息转发函数,并使子类具有一个名为“父类”转发到超类。超类本身只包含数据,然后我添加了功能特性。这有多酷?