Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics Scala';s(2.8)舱单工作?_Generics_Scala_Manifest - Fatal编程技术网

Generics Scala';s(2.8)舱单工作?

Generics Scala';s(2.8)舱单工作?,generics,scala,manifest,Generics,Scala,Manifest,我有一些大量使用泛型的Scala代码,我从文档中收集到,在参数化约束中使用清单可以帮助我解决类型擦除问题(例如,我想实例化泛型类型的新对象)。只是,我想更多地了解它是如何工作的。它几乎感觉像某种hashmap,为每个调用站点获取一个条目。。。这里有人能详细说明吗 class Image[T <: Pixel[T] : Manifest](fun() => T, size: Array[Int], data: Array[T]) { def this(fun: () =>

我有一些大量使用泛型的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));
    }
}
类映像[T,大小:数组[Int],数据:数组[T]){ 定义这个(乐趣:()=>T,大小:数组[T]){ 这个(有趣,大小,新数组[T](大小(0)*大小(1)); } }
我在网站上找到的任何文档似乎都没有涉及到这一点,而在谷歌上,我大部分都看到了语法非常不同的老帖子,而且2.8似乎有很多东西发生了变化,我不确定这些内容是否仍然准确。

上下文绑定
T…:Manifest
是隐式参数的语法糖:
(隐式man:Manifest[T])
。因此,在由
class Image
指定的类型构造函数的实例化点,编译器查找/提供用于类型参数
T
的实际类型的清单,并且该值“保持不变”生成的类实例贯穿其存在,并“锚定”每个特定的
Image[Something]
实例到其
T

的清单中。从我翻阅Scala的源代码试图回答相同的问题以来,已经有一段时间了……但我记得答案很简短-

Manifest是一种欺骗代码,允许编译器绕过类型擦除(在运行时不使用它)。它会导致在编译时为与Manifest匹配的可能输入类型生成多个代码路径

清单是隐式解析的,但如果在编译时对清单类型有任何歧义,编译器将停止

有了
清单
的副本,您就有了一些可用的东西。您通常想要的主要东西是通过
擦除
擦除的
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'?
豪尔赫·奥尔蒂斯(Jorge Ortiz)在这方面有一篇很棒的博文(尽管很老):

编辑

通过让Scala打印出擦除编译器阶段的结果,您实际上可以看到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();
        ()
      }
    }
  }
}
final类Main使用ScalaObject扩展java.lang.Object{
def this():对象主={
Main.super.this();
()
};
def main(argv:Array[java.lang.String]):单位={
val args:Array[java.lang.String]=argv;
{
最后一个类$anon扩展了java.lang.Object{
def this():匿名类$anon={
$anon.super.this();
()
};
类BoundedManifestCheck使用ScalaObject扩展了java.lang.Object{
private[this]val值:java.lang.Object=\;
隐式私有[this]val证据$1:scala.reflect.Manifest=\;
def this($outer:anonymous class$anon,value:java.lang.Object,证据$1:scala.reflect.Manifest):BoundedManifestCheck={
BoundedManifestCheck.super.this();
()
};
private[this]val m:scala.reflect.Manifest=scala.this.Predef.Manifest(BoundedManifestCheck.this.defence$1);
def m():scala.reflect.Manifest=BoundedManifestCheck.this.m;

if(BoundedManifestCheck.this.m()。可能重复。我不确定这些答案是否真的回答了它是如何工作的?至少它可能更清楚。编译器是不是在方法/函数中添加了一个额外的参数来保存泛型参数的具体类?还有什么问题?请看这里:感谢链接;它没有讨论清单,tho呃。谢谢,这很有帮助,不过我想知道这个值是如何与实例结合在一起的,即它保存的位置。与任何构造函数参数一样(在构造函数外部引用):在一个字段中。编辑我的答案以包含擦除阶段的输出。通过将
-Xprint:erasure
参数传递给编译器/运行时,实际上可以让Scalac向您显示它生成的内容。这将打印出擦除阶段运行后Scala代码的状态。另外值得注意的是,从f中删除
:Manifest
最后一个示例导致编译失败-
错误:调用
val m=Manifest[T]
时找不到参数m:Manifest[T]
的隐式值。上下文边界提供了
Manifest[\u]
调用需要操作的信息,因此它不是可选的。
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();
        ()
      }
    }
  }
}