2013-10-21 49 views
2

我有一个抽象的路径依赖类型,我需要ClassTag的。是否有比手动拉取每个具体派生类的隐式更好的方法?scala如何获得路径依赖类型的经验值

trait Foo { 
    type A // : ClassTag // Need the ClassTag of A later 
    val ctA: ClassTag[A] // But can't put a context-bound on the type 
} 

class IntFoo extends Foo { 
    type A = Int 
    val ctA = implicitly[ClassTag[Int]] 
} 

class StringFoo extends Foo { 
    type A = String 
    val ctA = implicitly[ClassTag[String]] 
} 

回答

3

你必须想出一个你知道类型的类标签。

scala> :pa 
// Entering paste mode (ctrl-D to finish) 

trait Foo { 
type A 
def ct[B: ClassTag] = implicitly[ClassTag[B]] 
} 

// Exiting paste mode, now interpreting. 

defined trait Foo 

scala> :pa 
// Entering paste mode (ctrl-D to finish) 

class IntFoo extends Foo { 
type A = Int 
def myct = ct[A] 
} 

// Exiting paste mode, now interpreting. 

defined class IntFoo 

scala> new IntFoo().myct 
res2: scala.reflect.ClassTag[Int] = Int 

但是这些日子的宏很容易写。

scala> :pa 
// Entering paste mode (ctrl-D to finish) 

object M { 
def ct[A: c.WeakTypeTag](c: Context): c.Expr[ClassTag[A]] = { 
import c.universe._ 
val a = c.prefix.tree.tpe.member(TypeName("A")).typeSignature 
c.Expr(q"implicitly[ClassTag[$a]]").asInstanceOf[c.Expr[ClassTag[A]]] 
}} 

// Exiting paste mode, now interpreting. 

scala> class Foo { type A = Int ; def f: ClassTag[A] = macro M.ct[A] } 
defined class Foo 

scala> new Foo().f 
res15: scala.reflect.ClassTag[Int] = Int 

scala> class Bar { type A = Char ; def f: ClassTag[A] = macro M.ct[A] } 
defined class Bar 

scala> new Bar().f 
res16: scala.reflect.ClassTag[Char] = Char 

所以

scala> trait Foo { type A ; def ct = macro M.ct[A] } 
defined trait Foo 

scala> class Bar extends Foo { type A = Int ; def p = println(ct) } 
defined class Bar 

scala> new Bar().p 
Int 
+0

谢谢,这看起来像没有比使用宏更好的办法。 – Woodz

+3

@Woodz我会说,“哦,男孩,现在我的老板/技术主管必须让我使用宏,我一直想用宏。” –

相关问题