如何最好地保留成员字段的缓存列表,每个成员字段都用于 Scala 中的一系列案例类 [英] How best to keep a cached list of member fields, one each for a family of case classes in Scala

查看:32
本文介绍了如何最好地保留成员字段的缓存列表,每个成员字段都用于 Scala 中的一系列案例类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是对以下问题的跟进:在 Scala 中获取案例类字段名称的最快方法

This is a follow up to the following question: Fastest way to get the names of the fields of a case class in Scala

我正在尝试找到一种简单的方法来提供快速的自定义序列化(比如 (String, Object) 的元组列表,它可以在生产中转换为 db 行或单元测试中的内存映射)到 Scala 中的一系列案例类,似乎保持类的字段的缓存列表可能是一种很有前途的方法.但是,我不确定最干净的方法来做到这一点.我知道我可以执行以下操作:

I'm trying to find a simple way to provide fast custom serialization (lets say to a list of tuples of (String, Object), which can be converted into a db row in production or an in memory map in unit testing) to a family of case classes in Scala, and it seems that keeping a cached list of a fields of the class may be a promising way of doing this. However, I'm not sure about the cleanest way to do this. I know I can do something like the following:

case class Playlist(
  val id: Option[Long],
  val title: Option[String],
  val album: Option[String],
  val artist: Option[String],
  val songId: Option[UUID]) {
  def serialize = Playlist.fields.map(f => (f.getName, f.get(this)))
}

object Playlist {
  val empty = Playlist(None, None, None, None, None)
  val fields = Playlist.empty.getClass.getDeclaredFields.toList
  fields foreach { _.setAccessible(true) }
}

然而,我不喜欢这方面的一些事情:

There a are a couple of things I don't like about this, however:

  1. 我不想为了获得缓存的字段列表而使用同伴类中的 empty
  2. 我不想为我想要这种序列化行为的每个案例类声明序列化逻辑.可能有几种方法可以解决这个问题,但我不确定最干净的方法可以提供正确的行为(担心混合反射和继承)

在 Scala 中实现这一目标的最简洁方法是什么?

What's the cleanest way to achieve this in Scala?

推荐答案

我认为保留 Class[_] 的缓存映射是最简单的 ->fields 与任何单个 case 类分开,例如在具有方法 serialize(instance) 的全局单例中.这样您就不必在要序列化的类中编写任何额外的代码.

I think it would be simplest to keep a cache map of Class[_] -> fields separately from any individual case class, such as in a global singleton with a method serialize(instance). This way you don't have to write any extra code in the classes you wish to serialize.

另一种方法可能是创建一个特征来混合到案例类的伴随对象,带有缓存的字段列表,以及一个隐式包装类来添加 serialize 方法.您可以使用隐式 ClassTag 来初始化 fields:

Another way could be to create a trait to mixin to the case classes' companion objects, with the cached list of fields, and an implicit wrapper class to add the serialize method. You can use an implicit ClassTag to initialize fields:

abstract class MyCompanion[T](implicit ctag: ClassTag[T]) {
    private val fields = ctag.runtimeClass.getDeclaredFields.toList
    fields foreach { _.setAccessible(true) }
    implicit class AddSerializeMethod(obj: T) {
        def serialize = fields.map(f => (f.getName, f.get(obj)))
    }
}

case class C(...) { ... }
object C extends MyCompanion[C]

不幸的是,您似乎无法通过这种方式使 AddSerializeMethod 成为值类.

Unfortunately, it seems you can't make AddSerializeMethod a value class this way.

这篇关于如何最好地保留成员字段的缓存列表,每个成员字段都用于 Scala 中的一系列案例类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆