浅析 Scala 构造器
2019-04-15
关键字:Scala 主构造器、Scala 辅助构造器、Scala 构造器的区别
本篇文章系笔者根据当前所掌握知识对 Scala 构造器的一些心得总结,不保证文章所述内容的绝对、完全正确性。
同 Java 一样,Scala 中的类的实例化过程也是从 构造器 开始的。只不过 Scala 中的构造器有两种
1. 主构造器;
2. 辅助构造器。
我们可以使用任一种构造器来实例化我们的类。不过,就本质上来说,主构造器 才是真正将我们的类实例化的构造器。下面我们就来简单探讨一下 Scala 中的这两种构造器的使用方式以及区别。
1、主构造器
在一个 Scala 类中,有且仅有一个主构造器。在我们对一个类实例化的时候,一定会调用主构造器,或显式调用或隐式调用的区别而已。下面的示例代码中红框部分即是主构造器的参数声明
带参主构造器
什么才是主构造器呢?
我们可以暂时把它理解成如上图所示那样,是一组直接跟在类名后面的参数列表。这个参数列表在声明的时候要注意了,没什么事最好不要漏掉 val / var 之类的声明符,漏掉的话,有可能它就不属于主构造器中的参数了。
那有的同学可能要问了:我在定义一个类的时候经常不带参数啊,一样跑的很 6 啊。就像下面这样
不带参数的主构造器
确实没错,以上两种类的定义都是各种没毛病的。但是同时每一个 Scala 类中都有且仅有一个主构造器。所以,到这里就要否决掉我们上面的那个 “暂时的理解” 了。主构造器是与类交织在一起的,它以一种你看不见摸不着但又事实存在的状态存在着。有一种简单的理解方式,我们可以直接把整个类体当成是主构造器。因为在一个类中,直接写在类体内的语句都属于主构造器的内容。还是拿上面的两个示例来说,那条 println 语句就会在主构造器被调用时执行。
那我们如何通过主构造器来实例化我们的类呢?直接 new 并传参就好了。
2、辅助构造器
Scala 对于辅助构造器的数量没有限制,我们可以在一个类中定义 0 ~ n 个辅助构造器。可以直接由辅助构造器来实例化一个类。我们甚至可以认为 Scala 的辅助构造器就是 Java 或者 C++ 中的普通构造器,因为它们之间的区别仅有以下两点
1. 构造器的名称统一为 this ;
2. 每一个辅助构造器都必须显式地调用其它辅助构造器或者主构造器。
以下是一个辅助构造器的示例代码
Scala 的辅助构造器
Scala 中辅助构造器的名称统一为 this ,不像 Java / C++ 是类名。据说这样做的目的是为了方便后续修改类名。
Scala 辅助构造器必须显式调用主构造器或者其它辅助构造器。在 Java 中只是多了一个隐式调用超类默认构造而已,也挺好理解的。记住就好了。
关于辅助构造器的使用,该怎么 new 就怎么 new 呗。我就懒得贴代码了,和 Java 是一样的。
主构造器与辅助构造器的番外知识
我们是否可以认为:无参的主构造器就是一个辅助构造器?
通过实例我们可以知道:在没有定义主构造器的参数列表时,我们在辅助构造器中调用的 this() 就代表着我们在调用主构造器。而且,在我们没有声明主构造器的参数时,是无法声明一个无参的辅助构造器的。
上面就是一个提示辅助构造器重名的情况。通过上面的报错提示,我们知道了默认的主构造器的名称就是 this() ,和无参辅助构造器是一样的。那它们是不是就是同一种东西了?
笔者认为:不是!
笔者认为两种构造器在某种情况下只是刚好重名了而已。在主构造器没有定义参数列表时,它的名字只是刚好叫作 this() 而已。在定义了带一个 Int 型参数的主构造器时,它的名字也只是刚好叫作 this(Int) 而已。不能简单地就认为主构造器和辅助构造器是同一种东西。应该是有一种 “形似神不似” 的感觉在里头。这个比较抽象,大家体会一下即可,同时我也不保证说我的这个观点就一定是正确的。
这篇文章是秉承 够用就好 的原则来写的。其实关于这两种构造器,笔者这篇文章中还有好多知识点是没有提到的。不提是因为笔者认为对于一个初学者来讲,并不需要弄懂所有的知识点,一些主要的,能解决你工作中大多数问题的点弄会了就可以了。要想深入钻研,还得靠日常工作中的积累。