Scala 不可变对象和具有 val 字段的特征

2024-02-14

我想仅使用不可变对象构建我的域模型。但我也想将特征与 val 字段一起使用,并将一些功能移至特征。请看下面的例子:

trait Versionable {
 val version = 0
 def incrementVersion = copy(version=version+1)
}

不幸的是,这样的代码不起作用 - 对于特征版本化来说,复制方法是未知的。

我认为为每个特征和类生成复制方法会很好。此类方法应创建对象的浅表副本,并使用与原始对象相同的类型返回它,并根据传递给方法的参数修改给定字段。

所以在下面的例子中:

class Customer(val name: String) extends Versionable {
 def changeName(newName: String) = copy(name = newName)
}

val customer = new Customer("Scot")

customer.changeName("McDonnald")应该返回一个对象实例Customer(version = 0, name = "McDonnald")

and

customer.incrementVersion还应该返回一个对象实例Customer(version = 1, name = "Scot")

据我所知,Scala 目前缺乏此类功能,不允许使用不可变的类和特征,而不用特征字段污染类构造函数。在我的示例中,我不想向 Customer 类引入名为 version 的参数,因为我希望将版本处理的功能封装在 Versionable 特征中。

我知道案例类中复制方法的功能以及使用默认参数在类中编写自己的复制方法的能力 - 但我认为此功能不能解决我的问题,因为不可能在特征中使用此类复制方法。现有功能的另一个缺点是使用复制方法的父类返回父类而不是实际复制的对象的类。

我的问题:

1)你知道如何以优雅的方式处理上面的例子吗?我对 Scala 很陌生,所以也许已经有很好的解决方案了。在我看来,优雅的解决方案应该具有以下特征:

  • 不应该使用反射

  • 不应该使用序列化

  • 应该很快

  • 应该在编译时可验证

2)您对编写编译器插件来为上面的示例生成复制方法的代码有何看法?是否可以使用编译器插件来做到这一点?您有任何示例或提示如何做到这一点吗?


最干净的解决方案可能是删除一些实现逻辑Versionable,并将其从类型堆栈中推入案例类(其中copy方法将可供您使用)。为版本属性指定默认值以完成设计。

trait Versioned {
  def version : Int
  def nextVersion = version + 1 
}

case class Customer(name: String, version : Int = 0) extends Versioned {
  def withName(newName: String) = copy(name = newName, version = nextVersion)
}

如果需要,您还可以在某处为版本编号定义类型别名:

type Version = Int
val initialVersion = 0

trait Versioned {
  def version : Version
  def nextVersion = version + 1 
}

case class Customer(name: String, version : Version = initialVersion)
extends Versioned {
  def withName(newName: String) = copy(name = newName, version = nextVersion)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala 不可变对象和具有 val 字段的特征 的相关文章

随机推荐

  • 标准输出重定向

    我正在使用 tcl 中的一个程序 我无法控制该程序 它在输出窗口上输出很多详细信息 例如 Response
  • 持久性实体的 GWT 反序列化 (JPA)

    我目前正在开发托管在 weblogic 应用程序服务器上的 Java GWT 应用程序 我使用 EJB3 0 和 EclipseLink 作为持久层 遗憾的是 我的 GWT 在反序列化持久实体时遇到问题 知道我可能会对你有所帮助 在我的类路
  • AutoMapper:如果源 == null,则创建目标类型的实例

    如果源对象为 null 是否可以将 AutoMapper 配置为返回目标类型的新实例 Source source null Dest d1 AutoMapper Mapper Map
  • Azure ServiceBus QueueClient.OnMessage 是否在不同的线程上执行

    QueueClient OnMessage 方法是否始终在不同线程上执行回调参数 我假设如果 MaxConcurrentCalls 设置为 10 那么queueClient 将最多启动 10 个线程来并行处理消息 如果传入 MaxConcu
  • .py 文件在浏览器中显示代码而不是运行

    我正在尝试开始使用 Python 但无法为 localhost 正确设置我的服务器 使用 Ampps Python 通过 IDLE 和命令行运行得很好 但是 当我在浏览器中打开文件时 代码会显示但不会运行 我跟着这个http www iml
  • 如何在 Azure 中选择 blob 块大小

    我想在 Azure 存储中使用追加 blob 当我上传 blob 时 我应该选择块大小 选择块大小时应该考虑什么 如果我上传的文件大小大于块大小 我看不出有什么区别 如何选择合适的块大小 根据你的描述 我做了一些研究 你可以参考它以更好地理
  • 运行 Hadoop 示例在伪分布式模式下停止

    在独立模式下一切都运行良好 当进入伪分布式模式时 HDFS 运行良好 我可以将文件放入 HDFS 并浏览它 我还检查了活动节点列表中是否有一个 DataNode 然而 当我跑步时bin hadoop jar hadoop examples
  • 如何更新控制中心的播放位置?

    这是我从指挥中心观察变化的方式 commandCenter playCommand addTarget self action selector play commandCenter pauseCommand addTarget self
  • 如何通过点击号码从 webviewclient 打开拨号器活动?

    我正在我的应用程序中实现网络视图 现在 当用户单击电话号码时 它会显示净 ERR UNKNOWN URL SCHEME 但如果我使用铬 它会带来带有该电话号码的拨号器应用程序 我的应用程序中需要完全相同的东西 当在 Web 视图中单击电话号
  • 我在表视图中显示 JSON 图像时遇到问题

    我正在尝试显示来自 API 的图像 这些图像位于 URL 内 我想用所有数组填充表视图 但它在表视图中只显示一张图像 这是我的代码 struct Autos let Marca String let Modelo String let Pr
  • INSERT INTO 因节点 mysql 失败

    我正在尝试使用 node js 插入一些数据 我编写了以下代码并通过 npm 安装了 MySQL 支持 但我失败了INSERT INTO桌子 这是我的代码 var mysql require mysql function BD var co
  • 尝试从视图中删除片段会在 mNextAnim 上出现 NullPointerException

    我有 3 个片段 1 个 NavigationDrawer 1 个 MapFragment 和 1 个用户定义的 MapInfoFragment 我希望 MapInfoFragment 在某些事件中在 MapFragment 顶部显示为半透
  • 如何防止 NC_CALCSIZE 调整我的表单大小? C#

    我正在创建一个自定义表单 C Windows Forms Vista Windows7 并重写 WndProc 来捕获 WM NCPAINT WM NCCALCSIZE 和 WM NCHITTEST 以绘制自定义框架 我快完成了 但有一个问
  • 如何解决“ruby安装缺少psych”错误?

    我使用rvm安装ruby 1 9 3 即使安装成功 它还是抱怨 libyaml 现在每次我想安装 gem 比如 Rails 时都会出现此警告 It seems your ruby installation is missing psych
  • drop_duplicates 在 pandas 中不起作用?

    我的代码的目的是导入 2 个 Excel 文件 比较它们 并将差异打印到新的 Excel 文件中 然而 在连接所有数据并使用drop duplicates函数 代码被控制台接受 但是 当打印到新的 Excel 文件时 当天仍保留重复项 我错
  • iTunes Connect 开发人员拒绝 - 删除不需要的构建/二进制文件

    我将二进制更新上传到新的 iTunesConnect 但尚未提交 我发现了一个错误 并尝试删除现有的二进制文件 找不到方法来做到这一点 然后我提交了审查 但立即被拒绝了 仍然找不到删除它并上传新的方法 如何上传我的新版本 或者如何取消更新并
  • Activity 泄露了 IntentReceiver android.widget.ViewFlipper

    我正在添加一个ViewFlipper从布局资源膨胀为ListView as a Footer 这是我的鳍状肢布局 为简洁起见 省略了详细信息
  • 跟踪 malloc 分配了多少内存

    在快速浏览了 SO 上的相关问题后 我推断没有函数可以检查 malloc 分配给指针的内存量 我正在尝试使用 C 中的简单 char 来复制一些 std string 基本功能 主要是动态大小 并且不想一直调用 realloc 我想我需要跟
  • Android studio gradle与firebase同步错误:响应204:无内容没有内容

    从今天早上开始 我在 android studio 中同步我的 android 项目时遇到了麻烦 当我尝试这样做时 我每次都会遇到相同的错误 部分错误 https i stack imgur com bD3S0 png 所有这些错误都是由同
  • Scala 不可变对象和具有 val 字段的特征

    我想仅使用不可变对象构建我的域模型 但我也想将特征与 val 字段一起使用 并将一些功能移至特征 请看下面的例子 trait Versionable val version 0 def incrementVersion copy versi