Ok so this isn’t a deep dive into implicit’s in scala but rather a reminder on how helpful they can be. The camp on using implicit in scala is divided as you can use them in several different ways and like everyone you’ll go crazy and use them everywhere, then you’ll stop.
Anyway implicit classes are an ideal way to add functionality to an existing type, huh? Ok so I get fed up of seeing this
val time = LocalTime.now() val someSpecialTime = SomeSpecialTime(time)
The code to me doesn’t read naturally anymore after using scala and I’d prefer time.toSomeSpecialTime, well there is a way if you use an implicit class:
object Converters { implicit class LocalTimeToSpecialTime(val localTime: LocalDateTime) extends AnyVal { def toSomeSpecialTime = SomeSpecialTime(time) def doSomthingElse = AnotherSpecialTime(time) } }
Now I can import the class and use it as I want.
The implicit class however can not be top level and MUST be defined in a scope where method calls are allowed -> package, class, object. I tend to wrap them inside an object.
I like to use them as a kind of factory, where a string is passed in and the correct type is returned.
def toSurfaceExtrapMethod: SurfExtrapolationMethod = { value match { case "SE_NONE" => SurfExtrapolationMethod.NONE() case SE_FLATLINE" => SurfExtrapolationMethod.FLATLINE() case "SE_FLATLINE_TO_ZERO" => SurfExtrapolationMethod.FLATLINE_TO_ZERO() case "SE_WITHIN_TOLERANCE" => SurfExtrapolationMethod.WITHIN_TOLERANCE() case "SE_STEP_UP_WITHIN_TOLERANCE" => SurfExtrapolationMethod.STEP_UP_WITHIN_TOLERANCE() } }
Also it’s possible to pass in values so you can have something like
def toRangeType(fixedRange: Option[FixedRange] = None): RangeType = { value match { case "FIT_BOTH" => RangeType.FitBoth() case "FIT_END" => RangeType.FitEnd() case "FIXED" => RangeType.Fixed(fixedRange.get) case "MIN_START" => RangeType.MinStart() }
So you can do something like
val rangeType = "FIXED".toRangeType(Some(FixedRange.FALSE))