Scala编译器如何从超类调用抽象方法?

时间:2018-09-20 10:38:45

标签: scala

我是Scala世界的新手,对OOPS概念有些困惑。这是我的代码段。

abstract class Element {
  def contents: Array[String]
  val lenth = contents.size
  val maxLength = contents.map(_.size).max
}
class ArrayElement(var contents: Array[String]) extends Element

据我了解,Scala编译器将为我们生成contents,contents_ =方法。因此我们可以避免在基类中定义def内容抽象方法。我的理解正确吗?如果是

val names = Array("welcome", "apple", "Test")
    val names1 = Array("apple", "Test")
    var t = new ArrayElement(names);
    println(t.contents.mkString(",")) //Op : welcome,apple,Test
    t.contents = names1 // because of var

#1 println(t.contents.mkString(“,”))// op:苹果,测试    #2 println(t.lenth)//在这里,我得到3(名字的长度)。但我期望2。为什么呢     #3 println(t.maxLength)//此处引用相同的名称。为什么?

'#1正在提供更新的名称列表。但是#2和#3提供了旧的名称引用。为什么呢

2 个答案:

答案 0 :(得分:3)

如果对 Element 类进行反编译,则会发现类似以下内容:

public abstract class Element {
  private final int lenth =  // call contents()
  private final int maxLength = // call contents()

  public abstract String[] contents();

  public int lenth() {
    return this.lenth;
  }

  public int maxLength() {
    return this.maxLength;
  }
}

因此 lenth maxLength 字段在对象创建阶段初始化一次,并且永远不会更改。

当您反编译ArrayElement类时,将出现以下内容:

public class ArrayElemen extends Element {

  private String[] contents;

  @Override
  public String[] contents() {
      return this.contents;
  }

  //...
}

因此,当您调用 t.contents 时,它将转换为 t.contents(),并返回更改后的值。

答案 1 :(得分:2)

maxLengthArrayElement都是对象ArrayElement的状态,并且在初始化期间仅更新一次 contents类。更改names1之后,lenth和maxLength都不会用lenth更新。

如果您要查找更新的maxLengthabstract class Element { def contents: Array[String] // val lenth = contents.size // val maxLength = contents.map(_.size).max def lenth = contents.size def maxLength = contents.map(_.size).max }

API

当然,您可以通过不同的方式实现这一目标。