问题
I'm trying to have a code like below:
object MetaData extends CacheParams{}
So, since CacheParams
needs implicit val p:Parameters
, I tried:
object MetaData (implicit val p: Parameters) extends CacheParams
But it seems that I can't pass arguments to an object.
( because it gives error:traits or objects may not have parameters
)
And if I don't pass any arguments it will give compile error that:
[error]: object creation impossible, since value p in trait CacheParams of type Parameters is not defined
I have no idea how to make this works. There were a few similar questions, but none of their answers solved my problem. Any help would be really appreciated. Thanks a lot.
回答1:
If I guessed the definition of CacheParams
correctly
trait Parameters
trait CacheParams {
implicit val p: Parameters
}
then you should: (1) replace the object
object MetaData /*(implicit val p: Parameters)*/ extends CacheParams
//object creation impossible. Missing implementation for:
// implicit val p: Parameters // inherited from trait CacheParams
with a class
class MetaData(implicit val p: Parameters) extends CacheParams
or (2) implement the implicit inside the object
object MetaData extends CacheParams {
override implicit val p: Parameters = new Parameters {}
}
or
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
In (1) you're defining/resolving implicit now in current scope. In (2) you postpone resolving implicit till instantiating the class (resolving implicit in the scope of class constructor call site).
See also Pass implicit parameter through multiply objects
Yeah that would solve my problem. But I wanted to keep the object's body clean and decoupled from the configuration in Parameters, like the classes' bodies that accept the
p: Parameters
.
If in (1) you want to decouple the object from "the configuration in Parameters
" you can try to introduce a trait (ParamsMaterializer
):
object MetaData extends CacheParams with ParamsMaterializer
trait ParamsMaterializer {
implicit val p: Parameters = new Parameters {}
}
or
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]
}
}
来源:https://stackoverflow.com/questions/64286575/extending-an-object-with-a-trait-which-needs-implicit-member