I need to update a field in a method which is called from many places. I want all values which are given to the field to be uppercase. But I don't want to transform it inside the methods where it's required. And don't want to create another value. I'm asking if I can use a type of implicits to transform the value?
def parent(itemType: String) =
getValue(itemType.toUperCase)
or
def parent(itemType: String) =
getValue(itemType)
getValue(itemType: String) = {
val formattedValue = itemType.toUperCase
}
I want to avoid both approaches, and ask for something like:
getValue(itemType: String = itemType.toUperCase) = {
// use itemType as upercase value
}
CodePudding user response:
The best thing would be to reify the uppercaseness in the type system.
import scala.language.implicitConversions
object Refined {
class UppercaseString private[Refined](override val toString: String) extends AnyVal
implicit def stringToUpper(s: String): UppercaseString = new UppercaseString(s.toUpperCase)
implicit def upperToString(ucs: UppercaseString): String = ucs.toString
}
Then you can express that a string must be uppercase (and transparently make a regular string uppercase) with
import Refined._
def getValue(itemType: UppercaseString) = ???
The presence of the implicit conversion to UppercaseString
means that, as long as Refined.stringToUpper
has been imported, we can call getValue
with arbitrary strings.
Because UppercaseString
extends AnyVal
, in many cases it will have no overhead beyond the uppercased string. Since it's a type, calling code can save it as an UppercaseString
and save calls to toUpperCase
.
Note that implicit class
doesn't work here as we want to perform an operation in the process of "construction"; the constructor of UppercaseString
is private
to Refined
so that we can ensure that all creation goes through toUpperCase
.