シンプルなタイプのビルダーをscalaでコーディングしたいと思います。とにかく、タイプビルダーそれは魅力のように自己作品。 typebuilderの抽象クラスをチェックしたいと思います。抽象型をチェックする際に奇妙なマクロの振る舞いがありますか?
はランタイムではそのための問題はありません。
if (classSymbol.isAbstract) throw new IllegalArgumentException("Provided class is abstract")
私はTypeTag属性を持つメソッドをタグ付けするので、Scalaはコンパイル時間を消去しないでください。
def createInstance[T: TypeTag]: T
とにかくこれは動作しています。私はこの方法を好むわけではないので、ユーザーは抽象クラスを入力してそれを作成することができます。私は実行時に引数の例外をチェックしたくありません。
コンパイル時間の間、正しいタイプをチェックするのは本当にクールだと思いました。「クラスでなければなりません」私はこのマクロを使用Evertime、私はアボートメッセージを取得
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)")
}
}
}
: これはマクロ関数の完全なコードです。 クラスか抽象タイプかは関係ありません。 使用法:
val typeInfo = typeOf[T]
val classSymbol = typeInfo.typeSymbol.asClass
ClassCheckMacro.checkClass(classSymbol)
は、この "奇妙な" 行動のための任意のヒントがありますか?
あなたは '' checkClass(新しいC)を意図していましたか? –
うん、何かある。 'new C'の場合は、typeSymbolを入れなければなりません。ジェネリック型の新しいインスタンスを作成できないからです; –
あなたはそれを呼び出す方法を誤解していると思います。 'class C'が与えられた場合、' checkClass [C](null) 'を試してみてください。 –