加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 如何匹配自定义泛型类型?

发布时间:2020-12-16 19:23:20 所属栏目:安全 来源:网络整理
导读:我正在尝试使用模式匹配来检测基于 this answer的我自己的自定义类型的泛型类型. 作者提供的代码按预期工作: import scala.reflect.runtime.{universe = ru}def matchList[A: ru.TypeTag](list: List[A]) = list match { case strlist: List[String @unchec
我正在尝试使用模式匹配来检测基于 this answer的我自己的自定义类型的泛型类型.

作者提供的代码按预期工作:

import scala.reflect.runtime.{universe => ru}

def matchList[A: ru.TypeTag](list: List[A]) = list match {
  case strlist: List[String @unchecked] if ru.typeOf[A] =:= ru.typeOf[String] => println("A list of strings!")
  case intlist: List[Int @unchecked] if ru.typeOf[A] =:= ru.typeOf[Int] => println("A list of ints!")
}

matchList(List("a","b","c"))
matchList(List(1,2,3))

正确显示:

A list of strings!
A list of ints!

现在基于此我试图应用相同的模式来检测我的自定义类Foo的泛型类型.下面的代码是copy-pased,除了它使用Foo而不是List:

import scala.reflect.runtime.{universe => ru}

class Foo[T](val data: T)

def matchFoo[A: ru.TypeTag](foo: Foo[A]) = {
  println("Is string = " + (ru.typeOf[A] =:= ru.typeOf[String]))
  println("Is int = " + (ru.typeOf[A] =:= ru.typeOf[Int]))
  foo match {
    case fooStr: Foo[String @unchecked] if ru.typeOf[A] =:= ru.typeOf[String] => println("Found String")
    case fooInt: Foo[Int @unchecked] if ru.typeOf[A] =:= ru.typeOf[Int] => println("Found Int")
  }
}

matchFoo(new Foo[String]("str"))
println("------------")
matchFoo(new Foo[Int](123))

只有这次它输出的不是我所期望的:

Is string = true
Is int = false
Found String
------------
Is string = false
Is int = true
Found String  // wth?

第二个调用matchFoo(new Foo [Int](123))如何显示Found String?正如你所看到的,我甚至明确地印出了比赛条件,他们很好.

在线代码:http://goo.gl/b5Ta7h

编辑:

我通过将匹配条件提取到变量中来实现它:

def matchFoo[A: ru.TypeTag](foo: Foo[A]) = {
    val isString: Boolean = ru.typeOf[A] =:= ru.typeOf[String]
    val isInt: Boolean = ru.typeOf[A] =:= ru.typeOf[Int]
    println("Is string = " + isString)
    println("Is int = " + isInt)
    foo match {
      case fooStr: Foo[String @unchecked] if isString => println("Found String")
      case fooInt: Foo[Int @unchecked] if isInt => println("Found Int")
    }
}

在线代码:http://goo.gl/mLxYY2

但在我看来,原始版本也应该有效.我不认为我在这里缺少运算符优先级,因为将条件包装到括号中也没有帮助.

它是Scala中的错误吗?我正在使用Scala SDK v.2.11.5和JDK v.1.8.0_25.在线CodingGround使用Scala SDK v.2.10.3.

编辑2:

我已经在Scala的bugtracker中打开了一个问题.你可以投票支持here.

解决方法

这看起来非常像编译器中的一个错误,它无法解析正确的隐式(可能是@unchecked的存在?).

case fooStr: Foo[String @unchecked] if ru.typeOf[A] =:= ru.typeOf[String] =>
   println(implicitly[TypeTag[String]]) // will print TypeTag[Int]

通过查看字节代码,编译器使用传递给方法的TypeTag($evidence).

(有限的)解决方法可能是使用ru.definitions.IntTpe:

case fooStr: Foo[Int @unchecked] if ru.typeOf[A] =:= ru.definitions.IntTpe =>
   println("That's an Int")

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读