案例类继承是禁止的,但是如何从库中建模依赖?

时间:2017-04-13 09:07:11

标签: scala playframework playframework-2.0

我有三个不同的Scala项目,其中一个只包含在其他两个Scala项目(以下简称库)中使用的模型。三个项目中的一个是Play Web应用程序,我想在MongoDB中保存库中的模型(代码驻留在Play应用程序中)。

所以在我的图书馆里我有以下模型:

case class MyUser(id: UUID = UUID.randomUUID(), timestamp: Instant = Instant.now, name: String)

要在我的Play应用中保留MyUser的实例,我通常会使用此模型:

case class MyUser(var _id: Option[BSONObjectID] = None,
                   id: UUID,
                   timestamp: Instant,
                   name: String,
                   var created: Option[DateTime] = None,
                   var updated: Option[DateTime] = None
                  ) extends Temporal

现在我正在寻找一种方法将我的库的MyUser变换为我的Play应用程序中的相应类,所以我想我会做这样的事情:

case class MyUser(var _id: Option[BSONObjectID] = None,
                   var created: Option[DateTime] = None,
                   var updated: Option[DateTime] = None
                  ) extends lib.MyUser with Temporal

但是,现在我收到以下错误:

  

禁止个案继承。要克服此限制,请使用提取器在非叶节点上进行模式匹配。

我想过做这样的事情:

case class MyUser(var _id: Option[BSONObjectID] = None,
                   user: lib.MyUser,
                   var created: Option[DateTime] = None,
                   var updated: Option[DateTime] = None
                  ) extends Temporal

我如何以正确的方式设计?

1 个答案:

答案 0 :(得分:2)

首先,错误告诉您的是,对于扩展的类,您不应该有case class。关于提取器的说法基本上是,如果需要在父类上进行模式匹配(这是case的{​​{1}}来自简单模式匹配),你总是可以编写自定义它的提取器。

但是,这不适用于您的情况,因为您无法更改您的lib公开case class es。

的事实。

另一个解决方案是考虑两个类之间没有继承。实际上,一个是用户的表示,而另一个是包含用户的存储单元的表示。所以看起来你提出的解决方案毕竟有一些意义。

但是,在序列化对象(在Mongo中)和JVM类中添加字段似乎很麻烦,在这种情况下,您需要始终case class来获取mongoUser.user来自lib.MyUser ...

一个优雅的(恕我直言)解决方案是保留此字段MyUser,但要让您的序列化将此字段展平到BSON对象的顶层,以便序列化的user: lib.MyUser看起来像< / p>

MyUser

好像您已经继承了{ _id: ObjectId(_), id: 123456789abc-1234-1234-1234, ... }

的字段

反序列化

现在,只要您想从Mongo获取lib.MyUser,仅出于读取目的,您可以直接以此格式反序列化它,忽略添加的字段。但是,如果您需要对其进行一些更新,则必须将其反序列化为lib.MyUser,以便能够更新此特定的BSON文档。

scala用法

如果您将对象反序列化为MyUser(例如,更新),您可能仍希望轻松访问MyUser中公开的所有字段,而无需访问字段{{ 1}}每一次。这可以通过隐式转换来完成。

<强>概括

顺便说一下,你可以通过一般的方式对任何你想要序列化的对象做这个......

总结一下

lib.MyUser