我定義了以下類來存盤物件的 classTag:
case class BindObj (bindTypeA: ClassTag[_], bindTypeB: ClassTag[_]) {
}
和模板函式如下:
def workOnThis[A, B](left: A, right: B): Unit => {
someOtherFunction(A, B)
...
}
預期用途如下:
def doWork(left: Anyref, right: Anyref, bindObj: BindObj): Unit => {
workOnThis[BindObj.bindTypeA, BindObj.bindTypeB](left.asInstance[BindObj.bindTypeA], right[BindObj.bindTypeB])
}
這段代碼顯然不起作用,因為模板型別需要在編譯時知道。但是是否有解決方法來實作預期用途?
uj5u.com熱心網友回復:
你的問題聽起來像XY 問題。您應該提供有關您實際想要做什么的更多詳細資訊。標準的 Scala 代碼可能就足夠了(可能帶有強制轉換),或者宏就足夠了(如果可以在編譯時完成),或者運行時反射就足夠了(至少沒有反射編譯)。
我假設您實際上僅在運行時擁有有關型別A, B( ClassTag[A], ClassTag[B]) 的資訊,并且該方法的workOnThis行為實際上取決于A, B。
看起來很奇怪,但原則上您可以執行以下操作:
import scala.reflect.api.TypeCreator
import scala.reflect.{ClassTag, api, classTag}
import scala.reflect.runtime.universe.{Quasiquote, Type, TypeTag, weakTypeOf}
import scala.reflect.runtime.{currentMirror => cm}
import scala.tools.reflect.ToolBox
object App {
val tb = cm.mkToolBox()
// from (1)
def backward[T](tpe: Type): TypeTag[T] =
TypeTag(cm, new TypeCreator {
override def apply[U <: api.Universe with Singleton](m: api.Mirror[U]): U#Type =
if (m eq cm) tpe.asInstanceOf[U#Type]
else throw new IllegalArgumentException(s"Type tag defined in $cm cannot be migrated to other mirrors.")
})
def classTagToTypeTag[T](classTag: ClassTag[T]): TypeTag[T] = {
val symbol = cm.classSymbol(classTag.runtimeClass)
symbol.typeParams // side effect
backward(symbol.toType)
}
case class BindObj(bindTypeA: ClassTag[_], bindTypeB: ClassTag[_])
def workOnThis[A, B](left: A, right: B): Unit =
println(s"A=${weakTypeOf[A]}, B=${weakTypeOf[B]}, left=$left, right=$right")
def doWork(left: AnyRef, right: AnyRef, bindObj: BindObj): Unit =
tb.eval(q"""
App.workOnThis[
${classTagToTypeTag(bindObj.bindTypeA)},
${classTagToTypeTag(bindObj.bindTypeB)}
](_, _)
""")
.asInstanceOf[(AnyRef, AnyRef) => Unit]
.apply(left, right)
class A
class B
def main(args: Array[String]): Unit = {
doWork(new A, new B, BindObj(classTag[A], classTag[B]))
// A=A, B=B, left=App$A@75e09567, right=App$B@2a334bac
}
}
(1)從一個Type中獲取一個TypeTag?
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/312785.html
上一篇:從akka-stream到fs2的旅程-如何使用http4s在fs2中定義一個akka-streamhttp流,如階段
