【问题标题】:Extending an object with a trait which needs implicit member扩展具有需要隐式成员的特征的对象
【发布时间】:2021-01-24 22:05:40
【问题描述】:

我正在尝试编写如下代码:

object MetaData extends CacheParams{}

所以,既然CacheParams需要implicit val p:Parameters,我就尝试了:

object MetaData (implicit val p: Parameters) extends CacheParams

但似乎我无法将参数传递给对象。

(因为它给出了错误:traits or objects may not have parameters

如果我不传递任何参数,它会给出编译错误:

[error]: object creation impossible, since value p in trait CacheParams of type Parameters is not defined

我不知道如何使它工作。有几个类似的问题,但他们的答案都没有解决我的问题。任何帮助将非常感激。 非常感谢。

【问题讨论】:

  • 为什么不在对象主体中覆盖p
  • 是的,这可以解决我的问题。但我想保持对象的主体干净并与参数中的配置分离,就像接受 p: 参数的类的主体一样。
  • ...或使用类代替对象
  • object 是一个单例,它不能接收参数,因为这样它就允许创建多个实例。所以要么使用class,要么修复对象定义中的隐含。

标签: scala implicit


【解决方案1】:

如果我猜对了CacheParams的定义

trait Parameters

trait CacheParams {
  implicit val p: Parameters
}

那么你应该:(1)替换对象

object MetaData /*(implicit val p: Parameters)*/ extends CacheParams

//object creation impossible. Missing implementation for:
//  implicit val p: Parameters // inherited from trait CacheParams

有一个类

class MetaData(implicit val p: Parameters) extends CacheParams

或(2)实现对象内部的隐式

object MetaData extends CacheParams {
  override implicit val p: Parameters = new Parameters {}
}

implicit val params: Parameters = new Parameters {} // suppose an implicit is in current scope

object MetaData extends CacheParams {
  override implicit val p: Parameters = {
    val p = ??? // hiding above p to avoid ambiguous implicits, null or NPE, see (*) below
    implicitly[Parameters]
  }
}

(*)NullPointerException on implicit resolution

在 (1) 中,您现在在当前范围内定义/解析隐式。在 (2) 中,您推迟解析隐式直到实例化类(在类构造函数调用站点的范围内解析隐式)。

另见Pass implicit parameter through multiply objects

是的,这将解决我的问题。但我想保持对象的主体干净并与参数中的配置分离,例如接受p: Parameters 的类的主体。

如果在 (1) 中您想将对象与“Parameters 中的配置”分离,您可以尝试引入一个特征 (ParamsMaterializer):

object MetaData extends CacheParams with ParamsMaterializer

trait ParamsMaterializer {
  implicit val p: Parameters = new Parameters {}
}

implicit val params: Parameters = new Parameters {} // suppose an implicit is in current scope

object MetaData extends CacheParams with ParamsMaterializer

trait ParamsMaterializer {
  implicit val p: Parameters = {
    val p = ???
    implicitly[Parameters]
  }
}

【讨论】:

    猜你喜欢
    • 2012-12-11
    • 2020-01-19
    • 1970-01-01
    • 1970-01-01
    • 2015-02-14
    • 2016-08-11
    • 2020-03-18
    • 1970-01-01
    • 2015-12-15
    相关资源
    最近更新 更多