泛型 – Scala(2.8)清单如何工作?
我有一些使用泛型的Scala代码,我从文档中收集到,在参数化约束中使用清单可以帮助我解决类型擦除问题(例如,我想实例化一般类型的新对象)。只有,我想了解更多关于这个工作原理。几乎感觉到某种类型的hashmap正在为每个调用站点获得一个条目。任何人都可以详细说明一下?
class Image[T <: Pixel[T] : Manifest](fun() => T,size: Array[Int],data: Array[T]) { def this(fun: () => T,size: Array[T]) { this(fun,size,new Array[T](size(0) * size(1)); } } 这在我在网站上发现的任何文档中似乎都没有涵盖,而在Google上我主要是收到具有非常不同语法的旧帖子,而且2.8版本似乎有很多改变, “不确定那些还是准确的。 解决方法
已经有一段时间,因为我挖掘了Scala的源代码,以回答同样的问题,但简而言之,我记得,
清单是一个欺骗代码,允许COMPILER绕过类型擦除(它不在运行时被使用)。它会导致在编译时生成与清单匹配的可能输入类型的多个代码路径。 清单被隐含地解析,但是如果在编译时有关于清单类型是什么歧义,编译器将停止。 有一个清单的副本你有几件事情可用。您通常需要的主要内容是通过擦除擦除的java.lang.Class: class BoundedManifest[T <: Any : Manifest](value: T) { val m = manifest[T] m.erasure.toString match { case "class java.lang.String" => println("String") case "double" | "int" => println("Numeric value.") case x => println("WTF is a '%s'?".format(x)) } } class ImplicitManifest[T <: Any](value: T)(implicit m: Manifest[T]) { m.erasure.toString match { case "class java.lang.String" => println("String") case "double" | "int" => println("Numeric value.") case x => println("WTF is a '%s'?".format(x)) } } new BoundedManifest("Foo Bar!") // String new BoundedManifest(5) // Numeric value. new BoundedManifest(5.2) // Numeric value. new BoundedManifest(BigDecimal("8.62234525")) // WTF is a 'class scala.math.BigDecimal'? new ImplicitManifest("Foo Bar!") // String new ImplicitManifest(5) // Numeric value. new ImplicitManifest(5.2) // Numeric value. new ImplicitManifest(BigDecimal("8.62234525")) // WTF is a 'class scala.math.BigDecimal'? 这是一个相当讽刺的例子,但显示了发生了什么。我在Scala 2.8上运行了输出以及FWIW。 Scala 2.8中的[T …:Manifest]边界是新的…您过去必须隐式地获取该清单,如ImplicitManifest所示。你实际上并没有获取清单的副本。但是您可以通过在Predef上定义val m = manifest [T] … manifest [_]来获取一个代码,并且可以在有界块中找到正确的清单类型。 您从清单获得的其他两个主要项目是<:<和>:>哪个测试一个清单的子类型/超类型与另一个清单。如果我记得正确,这些是非常天真的实现明智,并不总是匹配,但我有一堆生产代码使用它们来测试一些可能的擦除输入。检查另一个清单的简单示例: class BoundedManifestCheck[T <: Any : Manifest](value: T) { val m = manifest[T] if (m <:< manifest[AnyVal]) { println("AnyVal (primitive)") } else if (m <:< manifest[AnyRef]) { println("AnyRef") } else { println("Not sure what the base type of manifest '%s' is.".format(m.erasure)) } } new BoundedManifestCheck("Foo Bar!") // AnyRef new BoundedManifestCheck(5) // AnyVal (primitive) new BoundedManifestCheck(5.2) // AnyVal (primitive) new BoundedManifestCheck(BigDecimal("8.62234525")) // AnyRef Jorge Ortiz有一个伟大的博客文章(虽然很老):http://www.scala-blogs.org/2008/10/manifests-reified-types.html 编辑: 您可以通过要求打印出擦除编译器阶段的结果来查看Scala正在做什么。 运行,在我上面的例子scala -Xprint:erasure test.scala产生以下结果: final class Main extends java.lang.Object with ScalaObject { def this(): object Main = { Main.super.this(); () }; def main(argv: Array[java.lang.String]): Unit = { val args: Array[java.lang.String] = argv; { final class $anon extends java.lang.Object { def this(): anonymous class $anon = { $anon.super.this(); () }; class BoundedManifestCheck extends java.lang.Object with ScalaObject { <paramaccessor> private[this] val value: java.lang.Object = _; implicit <paramaccessor> private[this] val evidence$1: scala.reflect.Manifest = _; def this($outer: anonymous class $anon,value: java.lang.Object,evidence$1: scala.reflect.Manifest): BoundedManifestCheck = { BoundedManifestCheck.super.this(); () }; private[this] val m: scala.reflect.Manifest = scala.this.Predef.manifest(BoundedManifestCheck.this.evidence$1); <stable> <accessor> def m(): scala.reflect.Manifest = BoundedManifestCheck.this.m; if (BoundedManifestCheck.this.m().<:<(scala.this.Predef.manifest(reflect.this.Manifest.AnyVal()))) scala.this.Predef.println("AnyVal (primitive)") else if (BoundedManifestCheck.this.m().<:<(scala.this.Predef.manifest(reflect.this.Manifest.Object()))) scala.this.Predef.println("AnyRef") else scala.this.Predef.println(scala.this.Predef.augmentString("Not sure what the base type of manifest '%s' is.").format(scala.this.Predef.genericWrapArray(Array[java.lang.Object]{BoundedManifestCheck.this.m().erasure()}))); protected <synthetic> <paramaccessor> val $outer: anonymous class $anon = _; <synthetic> <stable> def Main$$anon$BoundedManifestCheck$$$outer(): anonymous class $anon = BoundedManifestCheck.this.$outer }; new BoundedManifestCheck($anon.this,"Foo Bar!",reflect.this.Manifest.classType(classOf[java.lang.String])); new BoundedManifestCheck($anon.this,scala.Int.box(5),reflect.this.Manifest.Int()); new BoundedManifestCheck($anon.this,scala.Double.box(5.2),reflect.this.Manifest.Double()); new BoundedManifestCheck($anon.this,scala.package.BigDecimal().apply("8.62234525"),reflect.this.Manifest.classType(classOf[scala.math.BigDecimal])) }; { new anonymous class $anon(); () } } } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |