Scala入门-构造器


Scala 构造器包括两种:主构造器和辅助构造器。

主构造器

object Construct01 {
  def main(args: Array[String]): Unit = {
    val p1 = new Person("Tom", 10)
    println(p1)

  }

  class Person(inName: String, inAge: Int) {
    var name: String = inName
    var age: Int = inAge

    // 重写 toString 方法,方便输出对象信息
    override def toString: String = {
      "name=" + this.name + "\t age" + this.age
    }
  }
}

几点注意:

  1. 主构造器的声明直接置于类名之后。
  2. 主构造器会执行类定义中的所有语句。
  3. 一个类如果没有显式定义主构造器则自动拥有一个无参的主构造器。
  4. 如果主构造器无参数,小括号可省略,构建对象时调用的构造方法的小括号也可省略。

关于第二点,我们这里查看编译后的字节码文件,一目了然。

  public static class Person {
    private String name;

    private int age;

    public String name() {
      return this.name;
    }

    public void name_$eq(String x$1) {
      this.name = x$1;
    }

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

    public void age_$eq(int x$1) {
      this.age = x$1;
    }

    public String toString() {
      return (new StringBuilder()).append("name=").append(name()).append("\t age").append(BoxesRunTime.boxToInteger(age())).toString();
    }

    public Person(String inName, int inAge) {
      this.name = inName;
      this.age = inAge;
      Predef$.MODULE$.println("-----"); // 对应源码中的 println("-----")
    }
  }
}

为了验证第二个观点,我在原有代码里有加了 println("-----")这条语句。在上面编译后的字节码中,可以清晰的看到 println 语句被加到了 Person 构造方法中。

辅构造器

辅助构造器使用关键字 this。

多个辅助构造器通过不同参数列表进行区分,即构造器的重载。

辅助构造器可以是直接或者间接调用主构造器。也就是说每个辅助构造器都必须以一个对先前已定义的其他辅助构造器或主构造器的调用开始。

下面重新定义一个 Person 类:

class Person2 {
  var name: String = _
  var age: Int = _
  // 辅助构造器
  def this(name : String) {
    // 辅助构造器无论是直接或间接,最终都一定要调用主构造器,执行主构造器的逻辑。
    this()  // 直接调用主构造器,且需要放在第一行。
    this.name = name
  }

  // 辅助构造器
  def this(name : String, age : Int) {
    this // 直接调用主构造器,这里省略了小括号。
    this.name = name
    this.age = age
  }

  def this(age : Int) {
    this("匿名") // 间接调用了主构造器,因为 def this(name : String) 该辅助构造器中调用了主构造器。
    this.age = age
  }
}

为了方便理解,可以与 Java 中的父子类构造器来进行类比。

我们知道 Java 中,子类构造器必须调用父类构造器,目的是在初始化当前子类对象时,先保证父类的初始化。如果子类构造器没有显示调用父类构造器,那么编译器会默认加上 super() 且放在子类构造器语句中的第一行。

如果指定了构造函数间的调用,那么 this 必须在第一行,以保证在执行任何动作前,对象已经完成了初始化。

对于间接调用,构造函数只能被构造函数调用,因为对象只会初始化一次。


文章作者: Tianny
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Tianny !
评论
 上一篇
Scala入门-构造器参数 Scala入门-构造器参数
Scala 构造器参数支持三种方式,默认无修饰符、使用 val 关键字声明、使用 var 关键字声明。 无修饰符Scala 类的主构造器的形参未用任何修饰符修饰,那么这个参数是局部变量。 比较简单,就不给出具体代码了。 使用 val 声明如
2020-03-19
下一篇 
Scala入门-类与对象 Scala入门-类与对象
创建类object BasicClass { def main(args: Array[String]): Unit = { val cat = new Cat cat.name = "Catty" cat.ag
2020-03-18
  目录