我想在scala中编写一个简单的类型构建器。无论如何,它自己的类型构建器就像一个魅力。 我想在typebuilder中查看抽象类。
在运行时,没有问题:
if (classSymbol.isAbstract) throw new IllegalArgumentException("Provided class is abstract")
我使用 TypeTag 属性标记方法,因此scala不会在编译期间删除时间。
def createInstance[T: TypeTag]: T
无论如何这是有效的。我不喜欢这种方式,因为用户可以输入抽象类并想要创建它。我不想在运行时检查参数异常。
所以我认为在编译时期间检查正确的类型真的很酷。 这是宏功能的完整代码:
object ClassCheckMacro {
def checkClass[T](x: T): T = macro checkClassImpl[T]
def checkClassImpl[T: c.WeakTypeTag](c: blackbox.Context)(x: c.Tree) = {
import c.universe._
val symbol = weakTypeOf[T].typeSymbol
if (symbol.isAbstract) {
c.abort(c.enclosingPosition, s"${symbol.fullName} must be a class")
} else {
c.Expr(q"($x)")
}
}
}
Evertime我使用这个宏,我得到中止消息"必须是一个类" 。 如果它是类或抽象类型并不重要。 用法:
val typeInfo = typeOf[T]
val classSymbol = typeInfo.typeSymbol.asClass
ClassCheckMacro.checkClass(classSymbol)
对此有任何提示吗?#34;奇怪"行为?
答案 0 :(得分:0)
x
只是一个值。
$ scalam -language:_
Welcome to Scala 2.12.0-M5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_92).
Type in expressions for evaluation. Or try :help.
scala> import reflect.macros._
import reflect.macros._
scala> def checkClassImpl[T: c.WeakTypeTag](c: blackbox.Context)(x: c.Tree) = {
| import c.universe._
| val symbol = weakTypeOf[T].typeSymbol
| if (symbol.isAbstract) {
| c.abort(c.enclosingPosition, s"${symbol.fullName} must be a class")
| } else {
| c.Expr(q"($x)")
| }
| }
checkClassImpl: [T](c: scala.reflect.macros.blackbox.Context)(x: c.Tree)(implicit evidence$1: c.WeakTypeTag[T])c.Expr[T]
scala> def checkClass[T](x: T): T = macro checkClassImpl[T]
defined term macro checkClass: [T](x: T)T
scala> class C
defined class C
scala> checkClass[C](null)
res0: C = null
scala> abstract class K
defined class K
scala> checkClass[K](null)
<console>:17: error: K must be a class
checkClass[K](null)
^
将工作笔记本电脑升级到Windows 10 ......