开发者学堂课程【Scala 核心编程-基础:主构造器和辅助构造器】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/609/detail/8949
主构造器和辅助构造器
内容简介
一、构造器
二、Scala 构造器注意事项和细节
一、构造器
1、Scala 构造器的介绍
(1)和 Java 一样,Scala 构造对象也需要调用构造方法,并且可以有任意多个构造方法;换句话说,Scala 构造器也可以重载;
(2)Scala 类的构造器包括:主构造器和辅助构造器
2、Scala 构造器的基本语法
class 类名(形参列表){//主构造器,并且只有一个(跟 Java 不一样,在 Java 中类名后面是不可以带形参的)
//类体
def this(形参列表){//辅助构造器
}
def this(形参列表){//辅助构造器,可以有多个...
}
(1)区别不同的辅助构造器
辅助构造器函数的名称 this,可以有多个,编译器通过不同参数来区分,参数可以是个数不一样,也可以是类型不一样,比如第一个辅助构造器只有一个参数,第二个辅助构建器有两个参数;当第一个构造器的类型是 int,第二个构造器的类型是 string,这样也可以区分开,这点跟 Java 是相同的。
3、Scala 构造器的快速入门
创建 Person 对象的同时初始化对象的 age 属性值和 name 属性值,案例演示。
操作演示:
先新建一个包,并设置名称,再新建一个文件;
代码设置:
package com. atguigu.chapter06.constructor
object ConDemo01 {
def main(args: Array[string]): unit = {
val p1 =new Person( "jack",20)
print Ln(p1)l
}
//构造器的快速入门
//创建 Person 对象的同时初始化对象的 age 属性值和 name 属性值
class Person(in Name : string, in Age : Int){
var name: string = in Name
var age: Int = in Age
/代码执行结果:
com.atguigu.chapter06.constructor.Person@4ec6a292这是类的信息/
/重写了 tostring,便于输出对象的信息
override def tostring: string = {
"name=” +this.name + "
\
t age" + this .age
执行结果:
Name=Jack age20
二、Scala 构造器注意事项和细节
1、Scala 构造器作用是完成对新对象的初始化,构造器没有返回值;可以从案例中发现是没有返回值的;
2、主构造器的声明直接放置于类名之后[反编译];比如代码 in Name : string, in Age : Int 看起来比较奇怪,构造器本就是方法,但此代码看着不伦不类的,其实在通过反编译之后,后面整体代码会放在构造器里面去,所以通过反编译是可以看到本质的。
3、主构造器会执行类定义中的所有语句,这里可以体会到 scala 的函数式编程;和面向对象编程融合在一起,即:构造器也是方法(函数),传递参数和使用方法和前面的函数部分内容没有区别【案例演示+反编译】;
详解:
可以在代码中直接输入一句话,这种做法在 Java 里面是不可能实现的,并且可以直接处理变量
添加后的代码如下:
class Person(in Name: string, in Age : Int) {
var name: string = in Name
var age: Int = in Age
age+= 10
print ln( "~~~~~~~~~~")
//重写了 tostring,便于输出对象的信息
override def tostring: string = {
"name=" + this.name + "lt age" + this. Age
}
print ln( "ok ~vmo~~")print ln( "age=" + age)
}
执行结果:
~~~~~~~~~~
Ok~~~~~
age=30
name=Jack age30
可以看到是按照顺序执行的,整个输出之后,代码 val p1 =new Person( "jack",20)便会导致输入,在调用 p1,然后输出 tostring。方法里面是不会执行的,可以看看是如何做的,打开反编译器,本质的东西一目了然,在构造器中,能看到所有编辑的代码被整体包装到一个构造器中。
可以理解成主构造器是所编辑的代码除去函数部分,都会被执行一遍。
4、如果主构造器无参数,小括号可省略,构建对象时调用的构造方法的小括号也可以省略。
详解:
把代码写出 val a=new A、val a2=new A()和 class A()其中一个都是可以的。
5、辅助构造器名称为 this(这个和 Java 是不一样的),多个辅助构造器通过不
同参数列表进行区分,在底层就是构造器的重载。【案例演示+反编译】
(1)代码设置:
package com.atguigu.chapter06.constructor
object ConDemoo1 {
d
ef main
(args:Array[
String])
:
unit={
//下面这句话就会调用 def this (name : string)
val p2 = new Person("tom")
p
rint ln(p2)
}
}
//构造器的快速入门
//创建 Person 对象的同时初始化对象的 age 属性值和 name 属性值
class Person( in Name: string, in Age : Int) {
var name: string = in Name
var age: Int = in Age
age +=10
print ln("~~~~~~~~~~")
//重写了 tostring,便于输出对象的信息 override def tostring: string = {
"name=” + this.name + "\t age"+ this. Age
print ln("ok ~~~~~~")
print ln( "age=" + age)
def this(name :string){
//只初始化年龄
//辅助构造器,必须在第一行显式调用主构造器
this( "jack",10)
this.name = name
执行结果:
~~~~~~~~~~
Ok~~~~~
age=20
name=tom age20
运行流程:首先是上传了姓名,其次调用了主构造器,代码 this( "jack",10)相当于是执行了 var 和 print ln 部分,做完主构造器的部分之后,又重新赋值了 name 部分,name 最终变成 Tom;如果没有这句话 this( "jack",10),会被报语法错误。辅助构造器,必须在第一行显式调用主构造器。
(2)Scala 设计者为什么要调用主构造器?
因为需要实现在调用主构造器时,需要调用主构造器的父类构造器,可以回忆在 Java 中是否存在这样的情况?在写Java 时,会有一个默认调用父类的程序,要是没有便会被报错。
(3)为什么要调用 this?
代码设置:
package com. atguigu.chapter06.constructor
object conDemo02 {
def main(args: Array [string]): unit ={
//转述
val a = new AA()
//构建了 A 的实例
)}
class BB{
print ln( "b~~~")}
class AA()extends
BB(){
def this(name : string) {
this
//调用 A 的主构造器
print ln( "A this( name : String)")
}
执行结果:
b~~~
在构建 AA 实例时,调用的是主构造器,调用主构造器又继承了 BB,此时走的代码是 print ln(“b~~~”),也会顺带调用 AA 父类的主构造器。
(4)在实现 AA 时,代码 val a = new AA()括号中什么都不写,会先走BB的主构造器,如果没有 this 辅助构造器,逻辑便讲不通,这样会导致跟父类的关系断掉,所以要先去调用主构造器的根本原因,是为了实现子类跟父类的继承关系,在 Java 中,要去实现子类,默认的父类构造器也会被调用。
(5)接下来讲代码中 val a = new AA()的括号里添加上“Jack”,变成 val a = new AA(“Jack”),再执行代码看结果;
代码如下:
package com. atguigu.chapter06.constructor
object conDemo02 {
def main(args: Array [string]): unit ={
val a = new AA(“jack”)
}
class BB(){
print ln( "b~~~")
class AA() extends BB() {
print ln( "AA()")
def this( name : string) {this
print ln( "A this( name : String)")
}
执行结果:
b~~~
AA()
A this (name : string)
执行顺序是会先去执行 AA 的主构造器,在执行 AA 的主构造器时,会优先执行 BB 里面的“b~~~”构造器,仍然是延用了 Java 机制。输出的顺序是,先是 b~~~父类,然后是AA()主构造器,再是 A this (name : string)辅助构造器。
(6)如果没有 this,辅助构造器不会去调用主构造器,代码中的联系便会断掉。在 Scala 中,对语言做了简化,不允许辅助构造器直接调用父类构造器,比如在代码中加入 super(),语法直接报错,因为在 Java 中,super()是调用父类构造器的意思,如果后面有参数,括号中决定调用父类中的哪个构造器所以在 Scala 中没有 super()。
(7)加强对辅助构造器的理解
代码如下:
package com. atguigu.chapter06.constructor
object conDemo03 {
def main(args: Array[string]):unit ={
val p1 = new Pe
r
son2(
)
}
//定义了一个 person 类
//person 一共有4个构造器
class Person2() {
var name: String =-
var age: Int =-
//这是两个属性
def this(name : string){
//辅助构造器无论是直接或间接,最终都一定要调用主构造器,执行主构造器的逻辑
//而且需要放在辅助构造器的第一行{这点和 java 一样,java 中一个构造器要调用同类的其它构造器,也需要放在第一行}
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
}
def show Info(): Unit = {
print Ln( "person信息如下:")
print ln( "name=” + this.name)
print ln( "age=" + this. age)
}
执行结果:
Process finished with exit code 0
再看看是否有四个 person,打开编译器查看,是有四个 person 的。
(8)在 Java 中,要调用同类构造器的代码设置如下:
package com. atguigu.chapter06.constructor;
public class JavaDemo01 {
public static void main( string[ ] args){
}
}
//构造器
class AAA {
public AAA(){
//这里调用 AAA(String name)
this( name: "aaa");
//必须放在第一行,在第一行前面会有一个默认 super(),但是两者不能同时存在
system. out. print ln( "AAA()");
}
//构造器
public AAA(String name){
super();
}