Reputation: 27385
I have a trait
trait Tr{
def logic: Option[() => Unit] = None
def apply(): Unit = logic match {
case Some(l) => l()
case None =>
}
}
object Tr{
implicit def procLogic2Opt(processingLogic: () => Unit): Option[() => Unit]
= Some(processingLogic)
}
The thing is when subclassing the trait I have to import Tr._
explicitly to bring implicits into a scope. Like this
import Tr._ //otherwise does not compile
class Trrr extends Tr{
override def processingLogic = () => println("test")
}
Is there a way to do it without importing explicitly? How could I redesign it?
Upvotes: 0
Views: 386
Reputation: 170745
Because the client is supposed to call only apply. I thought it's not necessary for subclassers to know that Option is required
So, why require it?
trait Tr {
protected val logic: () => Unit = () => {}
def apply(): Unit = logic()
}
class Trrr extends Tr{
override val logic = () => println("test")
}
(val logic
to avoid recreating it each time.)
Upvotes: 1
Reputation: 22374
Answering the headline question, if you really really really need it, move your implicit to trait:
trait Tr{
implicit def procLogic2Opt(...) = ...
}
This is not always a good practice though, because it's hard to find which implicit is responsible.
A story: In my previous project we had Logging trait with implicit (kind of) T => Any
which we inherited everywhere - imagine how many unexpected type conversions we had. Same goes for () => Unit
as many people might inherit your trait without even knowing about your implicit and wonder why functions other than apply
work when they shouldn't.
Besides implicit conversions (like your procLogic2Opt
) are a bad practice as well (almost always).
Quote from here:
Do not use implicits to do automatic conversions between similar datatypes (for example, converting a list to a stream); these are better done explicitly because the types have different semantics, and the reader should beware of these implications.
More precisely about your case: Scala Option implicit conversion - Bad practice or missing feature?
Use implicit-classes instead:
implicit class RichSomething(something: Something){
def toSomethingElse = ...
}
something.toSomethingElse
As mentioned in the comments your case is even simpler
Some(() => println("aaaa"))
class Trrr extends Tr{
override def logic = Some(() => println("test"))
}
This will give you explicit, easily understandable and discoverable types without wondering how () => Unit
became an Option[() => Unit]
Upvotes: 3