2015-07-03 3 views
0

Я пишу DSL, и у меня есть ситуация, когда мне нужно, чтобы значение было неявно преобразовано в любой тип. Я создал класс-оболочки со значением и неявным методом, который в основном работает:Scala: могу ли я получить доступ к типу типизированного метода?

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, чтобы я мог действовать соответствующим образом?

ответ

-1

Вы можете определить несколько функций, как

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.

+0

Это в настоящее время, что я делаю. Проблема в том, что он не может справиться со всеми возможностями. Например, пользователь может захотеть использовать свой собственный класс. Если возможно, я бы хотел получить решение, которое может обрабатывать любой класс. – DeegC

+0

'val str = ObjectOperationResult (" foo "); val i = str', это будет компилироваться как неявное преобразование 'ObjectOperationResult => Int' предоставляется' ObjectOperationResult.toInt', но будет работать как runtime из-за литого 'anyRefValyeOfStr.asInstanceOf [Int]'. Не безопасно для компиляции. – cchantep

-1

Один из способов сделать это - передать тип класса в качестве аргумента и условия для этого.

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