【问题标题】:How to pattern-match a generic type argument?如何对泛型类型参数进行模式匹配?
【发布时间】:2013-06-11 22:20:26
【问题描述】:

我目前无法完全理解 Scala 的 TypeTag 反射 API。在网络上可以找到的信息非常少,所有的尝试和错误尝试都无济于事。

def doStuff[T: TypeTag]( param: String ): SomeStuff[E] =
{
    val t = typeOf[T]

    if( <t extends one specific Trait from my application and is an object> )
    {
        <retrieve that companion object and return one of its values>
    }
    else
    {
        t match
        {
             case x if x =:= typeOf[String] => doOtherStuff[String]( param )
             case x if x =:= typeOf[Int] => doOtherStuff[Int]( param )
             ...
        }
    }
}

与 Scala 的预定义类型匹配的模式正在工作。但是,我没有设法检查提供的泛型参数是否继承了我的特定特征,然后在T 后面检索实际类的伴随对象。编译器拒绝直接尝试typeOf[MyTrait[_, T]],告诉我没有可用于 MyTag 的 TypeTag。如何创建它?

此外,Trait 令人讨厌的通用签名 MyTrait[M &lt;: MyTrait[M, E], E &lt;: Entity[M, E]] 正在加剧整个事情。

除了一些有用的想法来解决这个问题,我非常感谢任何进一步的阅读链接(尽管我已经阅读了所有关于 SO 的内容)。

【问题讨论】:

    标签: scala generics reflection runtime


    【解决方案1】:

    使用以下来测试它是否是一个对象(来自this question):

    typeOf[Test] <:< typeOf[Singleton]
    

    您可以使用存在类型来获取您的 trait 的 TypeTag

    typeOf[MyTrait[M, T] forSome { type M <: MyTrait[M, T] }]
    

    如果你有一个TypeTag[T] 在范围内并且绑定如下:

    T <: Entity[_,T]
    

    小例子:

    trait Entity[M, E]
    trait MyTrait[M <: MyTrait[M, E], E <: Entity[M, E]]
    
    class MyEnt extends Entity[Test, MyEnt]
    class Test extends MyTrait[Test, MyEnt]
    
    def getType[T <: Entity[_, T] : TypeTag] =
      typeOf[MyTrait[M,T] forSome { type M <: MyTrait[M,T] }]
    
    typeOf[Test] <:< getType[MyEnt]
    //| res0: Boolean = true
    

    但是,这不适用于您的情况,因为 T 的边界不正确。因此,您必须对此进行测试(在here 的帮助下):

    val mts = typeOf[MyTrait[_,_]].typeSymbol
    
    typeOf[Test].baseType(mts) match {
      case TypeRef(_, _, List(_, t)) if t <:< typeOf[MyEnt] => true
      case _ => false
    }
    

    【讨论】:

    • T 参数是无限的。它可能是MyTrait,但也可能只是Int。因此我不能使用getType 方法(因为通用边界不匹配)。有什么办法可以克服吗? (感谢您向我介绍forSome)。
    • @Taig 看来我们已经相互交叉了:P 这也引起了我的注意。我添加了另一个部分。
    猜你喜欢
    • 1970-01-01
    • 2013-04-10
    • 2011-10-25
    • 2016-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    • 1970-01-01
    相关资源
    最近更新 更多