Я пишу DSL, и у меня возникла ситуация, когда я хотел бы, чтобы значение было неявно преобразовано в любой тип. Я создал класс-оболочку со значением и неявным методом, который в основном работает:
case class ObjectOperationResult( val value: AnyRef )
object ObjectOperationResult {
implicit def result2T[ T ]( result: ObjectOperationResult ): T = {
result.value.asInstanceOf[ T ]
}
}
Код выдаст исключение, если result.value не является допустимым типом; пользователь должен убедиться, что он поступает правильно. Однако я хотел бы сделать его умнее, выполняя различную логику в зависимости от типа цели. Например, если целевой тип — String, вызовите toString вместо asInstanceOf[]; что-то вроде этого:
case class ObjectOperationResult( val value: AnyRef )
object ObjectOperationResult {
implicit def result2T[ T ]( result: ObjectOperationResult ): T = {
match T {
case String s: result.value.toString
case _ : result.value.asInstanceOf[ T ]
}
}
}
Это не компилируется; есть ли способ определить тип T, чтобы я мог действовать соответственно?
2 ответа
Вы можете определить несколько функций, например
object ObjectOperationResult {
implicit def toString( result: ObjectOperationResult ): String = result.value.toString.trim
implicit def toInt( result: ObjectOperationResult ): Int = result.value.asInstanceOf[Int]
}
Этот подход лучше по ряду причин:
1. Ваш код будет компилироваться только с правильными типами. Ошибки компиляции всегда лучше, чем ошибки времени выполнения 2. Вы можете вызвать эту функцию явно. Это может быть очень важно, если вы будете вызывать этот код из Java.
Один из способов сделать это — передать тип класса в качестве аргумента и условия для него.
import reflect.runtime.universe._
case class ObjectOperationResult( val value: AnyRef )
object ObjectOperationResult {
def result2T[T: TypeTag](c: Class[T], result: ObjectOperationResult): T = {
c match {
case s if typeOf[T] <:< typeOf[String] => result.value.toString.asInstanceOf[T]
case _ => result.value.asInstanceOf[T]
}
}
}
Вот как это можно использовать:
val a = ObjectOperationResult("hello")
val b = ObjectOperationResult(new java.util.Date())
ObjectOperationResult.result2T(classOf[String], a)
res0: String = hello
ObjectOperationResult.result2T(classOf[String], b)
res1: String = Fri Jul 03 13:15:12 PDT 2015
ObjectOperationResult.result2T(classOf[java.util.Date], b)
res2: java.util.Date = Fri Jul 03 13:15:12 PDT 2015
Похожие вопросы
Новые вопросы
scala
Scala - это язык программирования общего назначения, в основном предназначенный для виртуальной машины Java. Разработанный для краткого, элегантного и безопасного для типов представления общих шаблонов программирования, он сочетает в себе как императивный, так и функциональный стили программирования. Его ключевые особенности: продвинутая система статического типа с выводом типа; типы функций; сопоставления с образцом ; неявные параметры и преобразования; перегрузка оператора; полная совместимость с Java; совпадение
val str=ObjectOperationResult("foo"); val i=str
это будет скомпилировано, поскольку неявное преобразованиеObjectOperationResult => Int
обеспечиваетсяObjectOperationResult.toInt
, но во время выполнения произойдет сбой из-за приведенияanyRefValyeOfStr.asInstanceOf[Int]
. Не безопасно во время компиляции.