Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to declare traits as taking implicit "constructor parameters"?

I'm designing a class hierarchy, which consists of a base class along with several traits. The base class provides default implementations of several methods, and the traits selectively override certain methods via abstract override, so as to acts as stackable traits/mixins.

From a design perspective this works well, and maps to the domain so that I can add a filtering function from here (one trait) with a predicate from here (another trait) etc.

However, now I'd like some of my traits to take implicit parameters. I'm happy that this still makes sense from a design perspective, and wouldn't prove confusing in practice. However, I cannot convince the compiler to run with it.

The core of the problem seems to be that I cannot provide constructor arguments for a trait, such that they could be marked implicit. Referencing the implicit parameter within a method implementation fails to compile with the expected "could not find implicit value" message; I tried to "propagate" the implicit from construction stage (where, in practice, it's always in scope) to being available within the method via

implicit val e = implicitly[ClassName] 

but (as no doubt many of you expect) that definition failed with the same message.

It seems that the problem here is that I can't convince the compiler to tag the signature of the trait itself with an implicit ClassName flag, and force callers (i.e. those who mix the trait into an object) to provide the implicit. Currently my callers are doing so, but the compiler isn't checking at this level.


Is there any way to mark a trait as requiring certain implicits be available at construction time?

(And if not, is this simply not implemented yet or is there a deeper reason why this is impractical?)

like image 470
Andrzej Doyle Avatar asked Aug 08 '11 14:08

Andrzej Doyle


People also ask

How do you pass an implicit parameter?

The implicit parameter in Java is the object that the method belongs to. It's passed by specifying the reference or variable of the object before the name of the method. An implicit parameter is opposite to an explicit parameter, which is passed when specifying the parameter in the parenthesis of a method call.

What are implicit parameters?

What Are Implicit Parameters? Implicit parameters are similar to regular method parameters, except they could be passed to a method silently without going through the regular parameters list. A method can define a list of implicit parameters, that is placed after the list of regular parameters.


1 Answers

Actually, I've wanted this quite often before, but just came up with this idea. You can translate

trait T(implicit impl: ClassName) {   def foo = ... // using impl here } 

to [EDITED: original version didn't provide access to implicit for other methods]

trait T {   // no need to ever use it outside T   protected case class ClassNameW(implicit val wrapped: ClassName)    // normally defined by caller as val implWrap = ClassNameW    protected val implWrap: ClassNameW     // will have to repeat this when you extend T and need access to the implicit   import implWrap.wrapped    def foo = ... // using wrapped here } 
like image 196
Alexey Romanov Avatar answered Sep 22 '22 06:09

Alexey Romanov