特征和序列化/反序列化

2023-12-27

假设我有两个特征想混合到一个班级中。每个特征都实现类需要的抽象方法。

trait Writable {
    def serialize(out: java.io.DataOutput)
}

trait T1 extends Writable

trait A extends T1 {
   val aNum: Int
   abstract override def serialize(out: java.io.DataOutput) = {
       super.serialize(out)
       println("A serialize")
       out.writeInt(aNum)
   }

   def action = println("A action")
}

trait B extends T1 {
   val bNum: Int
   abstract override def serialize(out: java.io.DataOutput) = {
       super.serialize(out)
       println("B serialize")
       out.writeInt(bNum)
   }

   def action = println("B action")
}

abstract class M[CT1 <: T1](val mNum: Int) extends Writable {
   this: M[CT1] with T1 =>
   def serialize(out: java.io.DataOutput) = {
       println("M serialize")
       out.writeInt(mNum)
   }

   def action
}

然后我可以用 A 或 B 构造一个具体的 M 并序列化:

scala> val m1 = new M[A](10) with A { val aNum = 20 }
m1: M[A] with A = $anon$1@67c1e630

scala> val m2 = new M[B](20) with B { val bNum = 30 }
m2: M[B] with B = $anon$1@c36f58e

scala> val out = new java.io.DataOutputStream(new java.io.ByteArrayOutputStream())
out: java.io.DataOutputStream = java.io.DataOutputStream@87afebf

scala> m1.serialize(out)
M serialize
A serialize

scala> m2.serialize(out)
M serialize
B serialize

一切都按预期进行。但是如何反序列化对象,同时尊重混合到 M 中的特征类型?我可以在序列化方法中输出特征的名称,然后在名称上分派 M 的反序列化方法,但是如果我有除 M 之外的可以混合 A 和 B 的类怎么办?然后,每个类都必须重复 M 的调度反序列化的行为。如果我有多个特征需要混合到一个对象中以使其具体化,并且每个特征都有自己的自定义序列化/反序列化,那么问题会变得更糟。有人解决这样的问题吗?


是的,人们有。正确的方法是使用 David MacIver 倡导的类型类模式sbinary http://code.google.com/p/sbinary/和德巴什·戈什的sjson https://github.com/debasishg/sjson。德巴什的三部曲

  • Scala 隐式:类型类我来了 http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html
  • 重构为 Scala 类型类 http://debasishg.blogspot.com/2010/07/refactoring-into-scala-type-classes.html
  • sjson:现在在 Scala 中提供基于类型类的 JSON 序列化 http://debasishg.blogspot.com/2010/07/sjson-now-offers-type-class-based-json.html

对于所有中级 Scala 程序员特别有用。

如今,许多图书馆都在采用这种方法,包括我的图书馆scalaxb http://scalaxb.org/. See

  • 基于类型类的 XML 数据绑定 http://scalaxb.org/typeclass

我借用了 Scala Collections 的命名理念CanBuildFrom并将我的类型类命名如下:

trait CanReadXML[A] {
  def reads(seq: scala.xml.NodeSeq): Either[String, A]
}

trait CanWriteXML[A] {
  def writes(obj: A, namespace: Option[String], elementLabel: Option[String],
      scope: NamespaceBinding, typeAttribute: Boolean): NodeSeq
}

trait XMLFormat[A] extends CanWriteXML[A] with CanReadXML[A]

Edit:

你能向我解释一下框架如何在“with A”或“with B”之间进行选择吗?

使用类型类模式,这些库既不混合也不混合A nor B。 以scalaxb为例,它提供了一个名为scalaxb.fromXML在包对象中定义如下:

def fromXML[A](seq: NodeSeq, stack: List[ElemName] = Nil)
              (implicit format: XMLFormat[A]): A = format.reads(seq, stack) match {
  case Right(a) => a
  case Left(a) => throw new ParserFailure(a)
}

假设您有 XML 文档,并且您希望将其解组(反序列化)为ipo.Address对象,你会调用

scalaxb.fromXML[ipo.Address](<shipTo xmlns="http://www.example.com/IPO">
  <name>Foo</name>
  <street>1537 Paper Street</street>
  <city>Wilmington</city>
</shipTo>)

The Address对象使用类型类模式保持纯粹:

case class Address(name: String, street: String, city: String)

编译器如何知道要做什么?神奇的是所需的隐式参数fromXML called implicit format: XMLFormat[A]。这需要你有XMLFormat[Address]可用作范围内的隐式值,其中scalaxb.fromXML[ipo.Address](...)叫做。

这在 scalaxb 生成的代码中可用,因为它混合了XMLProtocol进入包对象ipo包裹。和ipo.XMLProtocol定义

implicit lazy val IpoAddressFormat: scalaxb.XMLFormat[ipo.Address] = new DefaultIpoAddressFormat {}

Edit2:

我想我开始理解真正的问题了。您有一个由特征混合组成的对象,并且您希望以某种方式“反序列化”其他进程上的特征组合。 正如您所写,您可以为每个特征添加一些标签,并加载任何可以加载的内容。

由于到目前为止我已经写了关于类型类模式的文章,所以让我继续该方法。拥有序列化代码的好处outside对象的特点是你实际上可以描述对象的 mixin 组合。假设有特征

trait Foo { def foo: Int }
trait Bar { def bar: Int }

你想将 mixin 描述为<obj><foo>1</foo><bar>2</bar></obj>。 这是一个gist https://gist.github.com/1121835我振作起来。 我定义了类型类实例Foo, Bar, and Foo with Bar,并称

Def.fromXML[Foo with Bar](<obj><foo>1</foo><bar>2</bar></obj>)

返回的

Right(FooWithBar(1, 2))
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

特征和序列化/反序列化 的相关文章

  • 如何捕获 Oozie Spark 输出

    有没有办法捕获spark的输出然后将其输入到shell上 我们当前正在使用 scala 创建 jar 文件 并希望我们的 Spark 输出成为 shell 输入 我的想法是使用 wf actionData spark XXXX var 我只
  • 在 Scala 和 SBT 中调试较长的编译时间

    在我的 Scala SBT 项目中 我有一个文件需要 5 分钟才能编译 所有其他的都可以在几秒钟内编译 这使得开发非常痛苦 我确信我滥用了一些 Scala 构造 但我不知道如何调试它 如何在 Scala 中调试较长的编译时间 我正在使用 S
  • 在 HBase 中存储和检索字符串数组

    我读过这个答案 如何将复杂对象存储到hadoop Hbase中 https stackoverflow com questions 4086684 how to store complex objects into hadoop hbase
  • Spark Scala 将列从一个数据帧复制到另一个数据帧

    我有一个原始数据框的修改版本 我在其上进行了聚类 现在我想将预测列恢复为原始 DF 索引没问题 因此匹配 我该怎么做 使用这段代码我得到一个错误 println Predicted dfWithOutput show println Ori
  • 使用spark phoenix从表中读取rdd分区号为1

    当我运行我的火花代码时 val sqlContext spark sqlContext val noact table primaryDataProcessor getTableData sqlContext zookeeper table
  • 对 Scala Not Null 特征的库支持

    Notice 从 Scala 2 11 开始 NotNull已弃用 据我了解 如果您希望引用类型不可为空 则必须混合魔法NotNull特征 编译器会自动阻止你输入null 可以值在里面 看到这个邮件列表线程 http www nabble
  • Java 中的“Lambdifying”scala 函数

    使用Java和Apache Spark 已用Scala重写 面对旧的API方法 org apache spark rdd JdbcRDD构造函数 其参数为 AbstractFunction1 abstract class AbstractF
  • 类型级编程有哪些示例? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我不明白 类型级编程 是什么意思 也无法使用Google找到合适的解释 有人可以提供一个演示类型级编程的示例吗 范式的解释和 或定义将
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • simpleframework,将空元素反序列化为空字符串而不是 null

    我使用简单框架 http simple sourceforge net http simple sourceforge net 在一个项目中满足我的序列化 反序列化需求 但在处理空 空字符串值时它不能按预期工作 好吧 至少不是我所期望的 如
  • 为什么在 Scala 中函数类型需要以单独的参数组传递到函数中

    我是 scala 新手 我用两种方式编写了相同的代码 但我对两种方式有点困惑 在第二种方式中 f 的参数类型是自动派生的 但在 type1 中 scala 编译器无法执行相同的操作 我只是想了解这背后的想法是什么 Type1 给出编译错误
  • 如何在 apache Spark 作业中执行阻塞 IO?

    如果当我遍历 RDD 时 我需要通过调用外部 阻塞 服务来计算数据集中的值怎么办 您认为如何才能实现这一目标 值 Future RDD Double Future sequence tasks 我尝试创建一个 Futures 列表 但由于
  • 在表单中编辑序列化哈希?

    我正在序列化存储在settings表中的字段 并且希望能够在表单字段中编辑该哈希 class Template lt ActiveRecord Base serialize settings end 但我就是这么做那么文本区域只显示序列化数
  • 如何使用“index_mut”来获取可变引用?

    即使当我实施IndexMut对于我的结构 我无法获得对结构内部向量元素的可变引用 use std ops Index IndexMut struct Test
  • Scala 交互式解释器 (REPL) - 如何将输出重定向到文本文件?

    是否可能 如果可能 是如何做到的 通常 gt and gt gt 在 Windows 或 Linux 命令行上工作的命令在这种情况下不起作用 您可以从控制台以编程方式执行此操作 import java io FileOutputStream
  • 如何使用泛型类型的 DataContractSerializer 编写自定义序列化器?

    我想编写一个自定义序列化器 用于将会话状态存储到Azure 缓存 预览版 这意味着这个自定义序列化器必须实现IDataCacheObjectSerializer 如果我错了 请告诉我 我需要编写这个自定义序列化程序的原因是我需要序列化一些包
  • Spark 数据帧:根据另一列的值提取一列

    我有一个包含带有连接价目表的交易的数据框 paid currency EUR USD GBP 49 5 EUR 99 79 69 客户已支付 49 5 欧元 如 货币 列中所示 我现在想将支付的价格与价目表中的价格进行比较 因此 我需要根据
  • java.io.Serialized 在 C/C++ 中的等价物是什么?

    C C 的等价物是什么java io Serialized https docs oracle com javase 7 docs api java io Serializable html 有对序列化库的引用 用 C 序列化数据结构 ht
  • 从 scala 的 Type 获取 ParameterizedType?

    有用的是 scala 的 Universe typeOf 保留了类的类型参数 import scala reflect runtime universe case class X T TypeTag val t typeOf T e g S
  • 根据 Slick 中的 Id 选择单行

    我想根据 Id 查询用户的一行 我有以下虚拟代码 case class User id Option Int name String object Users extends Table User user def id column In

随机推荐

  • redshift - 如何插入表生成的时间序列

    我正在尝试在 Redshift 中生成时间序列并插入表中 但没有成功 到目前为止我已经尝试过 insert into date dateid date SELECT to char datum YYYYMMDD int AS dateid
  • 有没有办法判断是否显示软键盘?

    有没有办法判断软键盘是否显示在活动中 I tried InputMethodManager manager InputMethodManager getSystemService getApplicationContext INPUT ME
  • Android Camera2 API - 检测我们何时获得焦点

    因此 我设法用旧相机按照我想要的方式创建了我想要的功能 使用 mCamera autoFocus autoFocusCallback 我检测何时获得焦点并在预览模式下运行所需的代码 现在我很难掌握如何在camera2 API 中执行相同的操
  • 完整的日历适合容器并隐藏滚动

    我无法弄清楚如何缩放 fullcalendar 以适应它的父容器 我想在单个页面上为用户显示周视图 而无需滚动 因此他们可以快速查看一周的项目 如果我需要使文本变小 插槽高度变小等 我没问题 但我只是不确定如何根据浏览器窗口的大小动态地执行
  • 在 C# 中使用“out”关键字返回多个值

    我目前正在努力理解它的含义 当它说使用 out 关键字我们能够return多个值 例如 来自 msdn 站点 https msdn microsoft com en us library ee332485 aspx https msdn m
  • Python 中的通用命令模式和命令调度模式

    我正在寻找一个CommandPython 中的模式实现 根据维基百科 http en wikipedia org wiki Command pattern 命令模式是一种设计 对象用于的模式 代表并封装所有 调用方法所需的信息 稍后 我唯一
  • JS 对象文字和 JSON 字符串有什么区别?

    我对人们所说的对象文字 JSON JavaScript 对象的确切含义感到困惑 对我来说 它们看起来很相似 foo bar bar baz AFAIK 上面是对象文字 json 以及 javascript 对象 不是吗 对象字面量和 jso
  • 如何确保打印偶数奇数的两个线程在此实现中保持先偶后奇的顺序?

    我创建了两个可运行的作业 PrintEvenNumbersJob 和 PrintOddNumbersJob 并生成了两个线程来执行这些作业 这似乎工作得很好 但我对这个实施感到有些可疑 我可以对这个实施有一些意见和建议吗 我在这个实现中看到
  • Python 是强类型的吗?

    我遇到过一些链接 说 Python 是一种强类型语言 但是 我认为在强类型语言中你不能这样做 bob 1 bob bob 我认为强类型语言不接受运行时的类型更改 也许我对强 弱类型的定义错误 或过于简单 那么 Python 是强类型语言还是
  • jQuery 在 AJAX 请求时同时发送 GET 和 POST 参数

    如何使用 jQuery AJAX 请求同时发送 GET 和 POST 参数 我正在尝试添加do ajax id ID to url 但结果请求仅打磨至sss php没有查询字符串 获取部分 谢谢 ajax url sss php do aj
  • 如何在 WIQL 工作项中获取层次结构

    我在 TFS 中有一个像这样的层次结构 其中 1 个功能可以有 N 个产品待办事项列表项目 而单个产品产品待办列表项目可以有 N 个任务 错误 树结构 特点1 gt PB1 gt 任务1 任务2 任务3 my Query string qu
  • 制作 Ubuntu 可执行文件

    我使用 gcc 编译器编写了一个 C 程序 现在它没有 GUI 组件 我正在使用 makefile 编译它并在终端中运行它 我需要部署它 以便可执行文件是独立的 我希望可执行文件有一个图标 单击时在终端中启动程序 谁能告诉我该怎么做 基础
  • SonarQube 中的质量门故障不会导致 Teamcity 中的构建失败

    我在 TeamCity 中建立了一个 Build 项目 并将 Sonarqube 与其集成 该项目正在构建 甚至在 SonarQube 控制台中成功发布报告 但当质量门失败时 它并不会破坏构建 我搜索并阅读了有关构建断路器的信息 但它已经受
  • 如何根据浏览器宽度动态调整CSS样式表?

    我们正在开发一款开源网络应用程序 供世界各地的艺术教师一起工作 我们需要一个漂亮的网站 它可以根据浏览器的活动宽度进行自我调整 就像 google org 或 barackobama com 做得很好一样 我们可以检测浏览器 操作系统等 但
  • 将请求记录到 django-rest-framework

    出于调试目的 我想使用 Django 的日志机制来记录每个传入请求 到达 django rest framework 的门口时的情况 Django 通过以下方式提供其请求的日志记录 仅 警告 日志级别及以上 来自 settings py 中
  • Apache 错误:无法加载 mod_access_compat.so

    我正在尝试运行 PHP 应用程序 但在尝试设置 Apache 2 4 时不断收到错误 错误是 httpd C Apache24 Apache24 conf httpd conf 第 72 行存在语法错误无法将 module mod acce
  • GitFlow:发布分支和主分支有什么区别?

    我刚刚看了一眼这个 gitflow 备忘单 http danielkummer github io git flow cheatsheet 我不明白release branch 谁能告诉我两者之间的区别release and master分
  • 在 AngularJS 中对对象数组进行分组

    基于如下所示的数组 var members name john team 1 name kevin team 1 name rob team 2 name matt team 2 name clint team 3 name will te
  • 如何获得 Firebase 节点的随机子节点?

    首先 这是我的数据库结构 我的目标是从 DE 节点获取一个随机问题对象以便稍后显示它 并且由于没有查询随机子项的内置支持 我必须自己从该迭代器以某种方式获取一个随机对象 目前 我有这段代码 但对如何将其串在一起感到困惑 DatabaseRe
  • 特征和序列化/反序列化

    假设我有两个特征想混合到一个班级中 每个特征都实现类需要的抽象方法 trait Writable def serialize out java io DataOutput trait T1 extends Writable trait A