如果Scala中的类型不相关,如何编写有效的类型有界代码

时间:2014-10-30 15:34:39

标签: scala scala-2.10

我想改进以下与Cassandra相关的Scala代码。我有两个不相关的user defined types,它们实际上是在Java源文件中(省略了详细信息)。

public class Blob { .. }
public class Meta { .. }

以下是我目前使用Scala的方法:

private val blobMapper: Mapper[Blob] = mappingManager.mapper(classOf[Blob])
private val metaMapper: Mapper[Meta] = mappingManager.mapper(classOf[Meta])

def save(entity: Object) = {
  entity match {
    case blob: Blob => blobMapper.saveAsync(blob)
    case meta: Meta => metaMapper.saveAsync(meta)
    case _ => // exception
 }
}

虽然这有效,但如何避免以下问题

  1. 在添加新的用户定义类型类(例如BlobMeta
  2. 时重复
  3. 添加save
  4. 等新方法时的模式匹配重复
  5. Object作为参数类型

2 个答案:

答案 0 :(得分:5)

您绝对可以使用Mapper作为类型类,执行:

def save[A](entity: A)(implicit mapper: Mapper[A]) = mapper.saveAsync(entity)

现在,您有一个通用方法,可以对A范围内的每个Mapper[A]类型执行保存操作。

此外,可能会改进mappingManager.mapper实现以避免classOf,但很难从当前状态的问题中看出来。

答案 1 :(得分:1)

几个问题:

  • mappingManager.mapper(cls)贵吗?
  • 您对处理Blob或Meta的子类有多关心?

这样的事情能为你效劳吗?

def save[T: Manifest](entity: T) = {
  mappingManager.mapper(manifest[T].runtimeClass).saveAsync(entity)
}

如果您确实关心确保Meta的子类获取正确的映射器,那么您可能会在isAssignableFrom中找到.mapper有用(并在HashMap中存储找到的子类,因此您只需要看一次)。

编辑:那么也许你想要这样的东西(忽略线程问题):

private[this] val mapperMap = mutable.HashMap[Class[_], Mapper[_]]()
def save[T: Manifest](entity: T) = {
  val cls = manifest[T].runtimeClass
  mapperMap.getOrElseUpdate(cls, mappingManager.mapper(cls))
    .asInstanceOf[Mapper[T]]
    .saveAsync(entity)
}