This is what I have come up with so far:
import reflect.runtime.universe.TypeTag
import scala.reflection.runtime.universe._
implicit class MyString(s: String) {
def getAs[T : TypeTag]: T = {
typeOf[T] match {
case t if t =:= typeOf[Int] => s.toInt.asInstanceOf[T]
case t if t =:= typeOf[Boolean] => s.toBoolean.asInstanceOf[T]
}
}
}
Running with this in REPL:
scala> "32".getAs[Int]
res25: Int = 32
scala> "32".getAs[Boolean]
java.lang.IllegalArgumentException: For input string: "32"
at scala.collection.immutable.StringLike$class.parseBoolean(StringLike.scala:290)
at scala.collection.immutable.StringLike$class.toBoolean(StringLike.scala:260)
at scala.collection.immutable.StringOps.toBoolean(StringOps.scala:30)
at MyString.getAs(<console>:33)
... 43 elided
scala> "false".getAs[Int]
java.lang.NumberFormatException: For input string: "false"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at scala.collection.immutable.StringLike$class.toInt(StringLike.scala:272)
at scala.collection.immutable.StringOps.toInt(StringOps.scala:30)
at MyString.getAs(<console>:32)
... 43 elided
scala> "false".getAs[Boolean]
res28: Boolean = false
scala> "false".getAs[String]
scala.MatchError: String (of class scala.reflect.internal.Types$AliasNoArgsTypeRef)
at MyString.getAs(<console>:31)
... 43 elided
Better, I think, would be to return an option[T]
, and catch any issues such as a type T
that isn't catered for, or attempting a cast that will fail. I started mucking around with scala's Try
(and its .toOption
method), but hit some odd errors so haven't gotten any further with that.
EDIT: just using a simple try-catch, we can get:
implicit class MyString(s: String) {
def getAs[T : TypeTag]: Option[T] = try {
typeOf[T] match {
case t if t =:= typeOf[Int] => Some(s.toInt.asInstanceOf[T])
case t if t =:= typeOf[Boolean] => Some(s.toBoolean.asInstanceOf[T])
}
} catch {
case ex: Exception => None
}
}
Resulting in:
scala> "false".getAs[String]
res30: Option[String] = None
scala> "32".getAs[Boolean]
res31: Option[Boolean] = None
scala> "32".getAs[Int]
res32: Option[Int] = Some(32)
scala> "true".getAs[Boolean]
res33: Option[Boolean] = Some(true)
scala> "true".getAs[Int]
res34: Option[Int] = None