我正在尝试编写一个返回Foo [T:ClassManifest]的工厂方法(由于我传递结果的库的要求,我需要它),而不知道具体是什么。我的代码相当于:
class Foo[T: ClassManifest] (t: T) {
def getValue: T = t
override def toString: String = "Foo["+t+": "+t.getClass().getName()+"]"
}
object FooFactory {
def parse (value: String): Foo[_] = {
val rest = value.substring(1)
value.head match {
case 's' => new Foo[String](rest)
case 'i' => new Foo[Int](rest.trim.toInt)
case 'd' => new Foo[Double](rest.trim.toDouble)
}
}
}
class FactoryTestSuite extends FunSuite {
def printIt [T: ClassManifest] (t: Foo[T]): Unit =
println(t)
test("Creation") {
printIt(FooFactory.parse("sabc"))
printIt(FooFactory.parse("i123"))
printIt(FooFactory.parse("d1.23"))
}
}
这不会编译 - 每个创建测试行都抱怨它could not find implicit value for evidence parameter of type ClassManifest[_$1]
有没有办法做到这一点?或者ClassManifest的编译时要求是否使得这根本不可能?
答案 0 :(得分:1)
parse
的结果类型为Foo[_]
,因此T
未知。对于未知类型,您无法获得ClassManifest
。只需从ClassManifest
T
(和printIt
)即可
def printIt(t: Foo[_]): Unit = println(t)
printIt(FooFactory.parse("sabc"))
// Foo[abc: java.lang.String]
printIt(FooFactory.parse("i123"))
// Foo[123: java.lang.Integer]
printIt(FooFactory.parse("d1.23"))
// Foo[1.23: java.lang.Double]
此处解析了ClassManifest[T]
构造函数的Foo
类型的隐式参数:
case 's' => new Foo[String](rest)
编译器知道T
这里是String
。它可以创建类型为ClassManifest[String]
的隐式参数。
要在方法ClassManifest
中获取printIt
,您可以将其添加为课程Foo
中的字段:
class Foo[T: ClassManifest] (t: T) {
val manifest = implicitly[ClassManifest[T]]
...
}
def printIt (t: Foo[_]): Unit =
println(s"t=$t, manifest=${t.manifest}")