scala – 如何匹配自定义泛型类型?
我正在尝试使用模式匹配来检测基于
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") (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |