djc*_*djc 23 generics scala manifest
我有一些Scala代码可以大量使用泛型,我从文档中收集到,在参数化约束中使用清单可以帮助我解决类型擦除问题(例如,我想实例化泛型类型的新对象) ).只是,我想更多地了解这是如何工作的.它几乎感觉像某种哈希映射为每个调用站点获取一个条目......这里有人可以详细说明吗?
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));
}
}
Run Code Online (Sandbox Code Playgroud)
这在我在网站上找到的任何文档中似乎都没有涉及,而在Google上我主要使用语法差别很大的旧文章,因为2.8似乎有很多变化,我我不确定那些仍然准确.
Bre*_*ams 35
自从我挖掘Scala的源代码以寻求回答同样的问题以来,已经有一段时间了......但我回忆起简短的回答 -
Manifest是一个作弊代码,允许COMPILER绕过类型擦除(它没有在运行时使用).它会导致在编译时为与清单匹配的可能输入类型生成多个代码路径.
Manifest是隐式解析的,但是如果在编译时有关Manifest类型的含义有什么歧义,编译器将停止.
有了一份副本,Manifest
你可以得到一些东西.您通常想要的主要内容java.lang.Class
是通过erasure
以下方式删除的内容:
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'?
Run Code Online (Sandbox Code Playgroud)
这是一个相当不稳定的例子,但显示了正在发生的事情.我在Scala 2.8上运行了输出以及FWIW.
该[T ... : Manifest]
边界是Scala 2.8新...你曾经有隐含抢清单所示ImplicitManifest
.你实际上并没有获得Manifest的副本.但是你可以通过说明val m = manifest[T]
... manifest[_]
定义来获取代码中的一个,Predef
并且明确地会在边界块中找到正确的清单类型.
另外两个主要项目,你从获得Manifest
IS <:<
和>:>
其测试亚型/一个清单与其他的超类型.如果我没记错的话,这些都是非常天真的实现,并不总是匹配,但我有一堆生产代码使用它们来测试几个可能的擦除输入.检查另一个清单的简单示例:
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
Run Code Online (Sandbox Code Playgroud)
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();
()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
9473 次 |
最近记录: |