Я не думаю, что есть способ, чтобы написать функцию как таковую с Manifest
, ClassTag
или TypeTag
как они могут только сказать вам тип во время выполнения. Чтобы что-то вроде функции псевдокода работало, возвращаемый тип должен быть известен во время компиляции.
Однако, можно реализовать функцию, указав type class и записывая экземпляры для типов, которые вы хотите отличить. Вот пример:
import java.lang.Double.parseDouble
import java.lang.Integer.parseInt
trait CastableFromString[A] {
def fromString(string: String): A
}
object CastableFromString {
implicit object DoubleCastableFromString extends CastableFromString[Double] {
override def fromString(string: String): Double =
parseDouble(string)
}
implicit object IntCastableFromString extends CastableFromString[Int] {
override def fromString(string: String): Int =
parseInt(string)
}
implicit object IntListCastableFromString extends CastableFromString[List[Int]] {
override def fromString(string: String): List[Int] =
string.split(',').map(parseInt).toList
}
def castFromString[A](string: String)(implicit cast: CastableFromString[A]): A =
cast.fromString(string)
}
object Main {
import CastableFromString._
def main(args: Array[String]): Unit = {
val d = castFromString[Double]("4.5")
val i = castFromString[Int]("42")
val li = castFromString[List[Int]]("1,2,3")
println(s"d=$d i=$i li=$li")
}
}
В качестве альтернативы, чтобы приблизиться к чему-то, что напоминает ваш псевдокод, вы могли бы использовать macro. Вот пример (не будет работать ни на чем старше Scala 2.11):
import scala.language.experimental.macros
import scala.reflect.macros.blackbox.Context
class StringCasterImpl(val c: Context) {
def castFromStringImpl[A: c.WeakTypeTag](string: c.Expr[String]): c.Tree = {
import c.universe._
val t = c.weakTypeOf[A]
if (t =:= typeOf[Double]) {
q"java.lang.Double.parseDouble($string)"
} else if (t =:= typeOf[Int]) {
q"java.lang.Integer.parseInt($string)"
} else if (t =:= typeOf[List[Int]]) {
q"$string.split(',').map(java.lang.Integer.parseInt).toList"
} else {
c.abort(c.enclosingPosition, s"Don't know how to cast $t to String")
}
}
}
object StringCaster {
def castFromString[A](string: String): A =
macro StringCasterImpl.castFromStringImpl[A]
}
// note that this object must be in a separate compilation unit
object Main {
import StringCaster._
def main(args: Array[String]): Unit = {
val d = castFromString[Double]("4.2")
val i = castFromString[Int]("42")
val li = castFromString[List[Int]]("1,2,3")
println(s"d=$d i=$i li=$li")
}
}
Я думаю, что вы имели в виду 'A: ClassTag' /' A: TypeTag', 'Manifest's являются устаревшими. Проверьте [это руководство] (http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html). –