1

我不太确定如何表达这个问题,因为我真的不明白发生了什么。但是我希望清单能够告诉我实例的实际运行时类型,它似乎告诉我分配给它的变量的运行时类型。

// scala 2.10.1
trait Base
class Impl1 extends Base
class Impl2 extends Base

def showManifest[T <: Base](thing: T)(implicit ev: Manifest[T]) = println(thing + ": " + ev.runtimeClass)

val (impl1, impl2) = (new Impl1, new Impl2)

println("=== impl1 and impl2 ===")
showManifest(impl1)
showManifest(impl2)

val choose1 = if(true) impl1 else impl2
val choose2 = if(false) impl1 else impl2

println("=== choose1 and choose2 ===")
showManifest(choose1)
showManifest(choose2)

输出:

=== impl1 and impl2 ===
Main$$anon$1$Impl1@48ff2413: class Main$$anon$1$Impl1
Main$$anon$1$Impl2@669980d5: class Main$$anon$1$Impl2
=== choose1 and choose2 ===
Main$$anon$1$Impl1@48ff2413: interface Main$$anon$1$Base
Main$$anon$1$Impl2@669980d5: interface Main$$anon$1$Base

那么,choose1 和choose2 的类型是Base,这就是为什么该方法以Manifest[Base] 结尾的原因吗?有没有办法解决这个问题,以便我可以在编译时选择我不知道的类型(通过配置参数等选择)并将其传递给工厂方法?

4

1 回答 1

2

这对我来说似乎一切正常。在您调用的所有实例中showManifest,您都在遵循类型推断来确定类型,而不是显式地传入类型(即showManifest[Impl1](impl1))。因此,您看到的与清单相关的类型将与val您传入的类型相匹配。在前两种情况下,类型推断知道确切的具体类型,并且您会在showManifest打印的内容中看到这一点。在后两种情况下,由于条件,类型推断在编译时并不确切知道它最终会是哪一种,因此它会向上移动这两种类型的类型层次结构,直到找到一个最终为Base.

我想如果你想尝试解决这种行为,你可以尝试这样的事情:

import scala.reflect.ManifestFactory
showManifest(choose1)(ManifestFactory.classType(choose1.getClass()))

此外,您可能应该像Scala 2.10 中已弃用的那样将事情切换到TypeTags/ ClassTagsManifest

于 2013-09-24T17:22:22.940 回答