【问题标题】:Scala abstract class instanceScala抽象类实例
【发布时间】:2018-06-24 15:35:32
【问题描述】:

我是 Scala 新手。我对 List 类有疑问。这是一个抽象的密封类。这意味着不能实例化,也不能扩展。那么它的用途是什么?像下面这样的东西怎么会起作用?

val myList = List(1,2,3)

myList 会是对 List 对象的引用吗? 另外,如果 productElement 是一个抽象方法,如何实现?

谢谢。

【问题讨论】:

    标签: scala abstract-class


    【解决方案1】:

    sealed 表示它不能扩展到定义它的文件之外。 List 是 sealed,但它确实在同一个文件中定义了 2 个非抽象子类:Nil:: 分别代表一个空列表和一个非空列表。

    当您调用List(1,2,3) 时,您并没有真正直接实例化List 类。它是List.apply(1, 2, 3) 的语法糖,它调用List 对象上的apply 方法(与List 类一起使用)。该方法(技术上通过某种间接方式)最终会生成Nil:: 的实例。

    您可以在此处查看列表子类: https://github.com/scala/scala/blob/2.13.x/src/library/scala/collection/immutable/List.scala#L547 https://github.com/scala/scala/blob/2.13.x/src/library/scala/collection/immutable/List.scala#L554

    您不需要实现productElement,它是由 scala 编译器为所有案例类创建的。

    【讨论】:

    • 谢谢,清楚。那么如何实现它的抽象方法,比如 productElement 呢?
    【解决方案2】:

    关于:

    val myList = List(1,2,3)
    

    当编译器遇到一个创建一个没有new 修饰符的类实例的表达式时,它会查找该类的伴随对象以查找.apply 方法。在list的情况下,定义为:

    override def apply[A](xs: A*): List[A] = xs.toList
    

    因此,编译成功。您可以在要求编译器在 typer 阶段之后发出类型信息时查看此内容:

    def main(args: Array[String]): Unit = {
      val l: List[Int] = scala.collection.immutable.List.apply[Int](1, 2, 3);
      ()
    }
    

    myList 会是对 List 对象的引用吗?

    myList 的运行时类型可以是 cons (::) 或空列表 (Nil)。

    如果 productElement 是一个抽象方法,如何实现?

    这是一个编译器技巧。 productElementproductArity(以及更多)都是在编译时为任何案例类定义生成的。例如,给定以下案例类:

    case class Bar(i: Int)
    

    编译器生成:

    // an incomplete view of the generated case class methods and fields
    // omitted for brevity.
    case class Bar extends AnyRef with Product with Serializable {
      <caseaccessor> <paramaccessor> private[this] val i: Int = _;
      <stable> <caseaccessor> <accessor> <paramaccessor> def i: Int = Bar.this.i;
      def <init>(i: Int): yuval.tests.Foo.Bar = {
        Bar.super.<init>();
        ()
      };
      <synthetic> def copy(i: Int = i): yuval.tests.Foo.Bar = new Bar(i);
      <synthetic> def copy$default$1: Int = Bar.this.i;
      override <synthetic> def productPrefix: String = "Bar";
    
      // this is the relevant part to your question
      <synthetic> def productArity: Int = 1;
      <synthetic> def productElement(x$1: Int): Any = x$1 match {
        case 0 => Bar.this.i
        case _ => throw new IndexOutOfBoundsException(x$1.toString())
      };
    

    【讨论】:

    • 谢谢。因此productElementproductArity 是由编译器实现的?
    • @toto' 是的,他们是。
    猜你喜欢
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 2017-02-05
    • 2012-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多