配置映射中的 scala 类名

Posted

技术标签:

【中文标题】配置映射中的 scala 类名【英文标题】:scala class names in configuration map 【发布时间】:2016-07-31 09:03:15 【问题描述】:

我有一个基于 play 框架的网络应用程序。

我的一个端点提供由不同类的输出组成的响应。消费者可以选择他希望在响应中具有哪些输出: GET /model/:modelId?fields=length,width,age。 因此,我有LengthProviderWidthProvider。 现在,我想在控制器中有一个配置映射,比如

val providers = Map(
    "length" -> LengthProvider,
    "width"  -> WidthProvider
)

能够通过此映射过滤消费者的输入并应用所有提供者,例如

fields.collect 
    case field if providers.contains(field) => providers(field)(db).get(modelId)
  

当我尝试构建相应的类时会出现问题。 我有一个摘要FieldProvider

abstract class FieldProvider(db: DB) 
  def get(modelId: Long): Future[Seq[Writes]]

以及相应的实现(LengthProviderWidthProvider)。现在,要编译配置 Map,我需要为要引用的类定义伴随对象(例如,我需要 LengthProvider 对象)。然后,当我使用 Map 的值(类名)时,我无法像通常那样初始化类实例,我只能访问伴随对象中定义的 apply 方法。但问题是这不是我定义的抽象类的一部分,所以编译器不理解apply 方法签名(因为它只在子类的伴随对象中定义,而不是在父抽象类中):

fields.collect 
    case field if providers.contains(field) => providers(field)(db).get(modelId)
                                                                ↑ won't compile
  

有没有办法让伴生对象的apply 签名成为抽象类的一部分?还是有其他更好的方法?

【问题讨论】:

【参考方案1】:

由于地图中的实例实际上是伴生对象,您可以让伴生对象从 Function1 继承,例如:

object LengthProvider extends ((DB) => LengthProvider) 
  def apply(v1: DB): LengthProvider = new LengthProvider(v1)


object WidthProvider extends ((DB) => WidthProvider) 
 def apply(v1: DB): WidthProvider = new WidthProvider(v1)


val providers: Map[String, ((DB) => FieldProvider)] = Map(
  "length" -> LengthProvider,
  "width"  -> WidthProvider
)

【讨论】:

这很好用!现在我有一个问题,事实上,LengthProvider 也需要一个隐式参数。可以通过伴随对象中的apply 方法以某种方式转发它吗?

以上是关于配置映射中的 scala 类名的主要内容,如果未能解决你的问题,请参考以下文章

大数据Scala学习—列表 集与映射

hibernate映射postgreSQL数据库中的表时,表名是大写的时候为啥hibernate不能映射实体

Scala 模式匹配详解

Scala中的环境特定配置

理解Scala的函数式编程思想

容器部署spark+hadoop+java+scala+推荐服务