Scala主要构造函数
在本文中,我们将通过实时场景示例深入讨论Scala主构造函数。
介绍
众所周知,构造函数用于创建类的实例。
Scala以与Java不同的方式支持构造函数。
在Scala语言中,一个类可以具有两种类型的构造函数:
- 主要构造函数
- 辅助构造函数
Scala类只能包含主构造函数,也可以包含主构造函数和辅助构造函数。
Scala类可以包含一个并且只能包含一个Primary构造函数,但是可以包含任意数量的Auxiliary构造函数。
我们将在这篇文章中详细讨论主要构造函数,而在我的后续文章中将讨论辅助构造函数的细节。
在进入下一部分之前,我们需要了解类定义和类主体,如下图所示:
类主体用两个大括号" {}"定义。
第一行是类定义。
Scala的主要构造函数
在Scala中,主要构造函数是一个从Class定义开始并跨越完整Class主体的构造函数。
我们可以使用零个或者一个或者多个参数定义主构造函数。
现在,我们将通过一些简单的示例逐一讨论它们。
示例1:-使用默认的Primary Constructor创建一个Person类。
class Person{ //Class body goes here }
其中我们定义了无参数或者零参数构造函数,例如" Person()"。
在Java中也称为"默认构造函数"。
我们可以创建一个Person类的实例,如下所示:
val p1 = new Person() var p2 = new Person
两者均在Scala中有效。
我们可以使用不带括号的无参数构造函数。
示例2:-在类名之后声明主要构造函数的参数,如下所示:
class Person(firstName:String, middleName:String, lastName:String){ //Class body goes here }
这里Person类的主要构造函数具有三个参数:firstName,middleName和lastName。
现在,我们可以创建一个Person类的实例,如下所示:
val p1 = new Person("First","","Last")
如果我们观察此示例,则某些人员可能具有中间名,但仍必须提供所有3个参数。
这不是在Scala中处理构造函数的有效方法。
我们可以使用辅助构造函数来解决此问题(请阅读我的下一篇文章)。
例3:除方法定义外,我们放在类体内的任何东西都是主构造函数的一部分。
class Person(firstName:String, middleName:String, lastName:String){ println("Statement 1") def fullName() = firstName + middleName + lastName println("Statement 2") }
当在Scala REPL中执行上述程序时,我们将获得以下输出:
scala> var p1 = new Person("Ram","","Posa") Statement 1 Statement 2 p1: Person = Person@3eb81efb
如果我们观察到该输出,因为两个println语句都在类主体中定义,则它们将成为主构造函数的一部分。
示例4:-:-类主体中定义的任何语句或者循环(如If..else,While,For等)也将成为主构造函数的一部分。
class Person(firstName:String, middleName:String, lastName:String){ def fullName() = firstName + middleName + lastName if (middleName.trim.length ==0) println("Middle Name is empty.") }
输出:
scala> var p1 = new Person("Ram","","Posa") Middle Name is empty. p1: Person = Person@64a40280
示例5:-:-不仅在语句或者表达式中,在类主体中定义的任何方法调用也将成为主构造函数的一部分。
class Person(firstName:String, middleName:String, lastName:String){ def fullName() = firstName + middleName + lastName fullName //A No-argument Method Call }
输出:
scala> var p1 = new Person("Ram","-","Posa") Ram-Posa p1: Person = Person@64a40280
Scala Val和var简要介绍
在讨论Scala主构造函数之前,我们需要重新讨论Scala字段定义概念。
在Scala中," val"和" var"用于定义类字段,构造函数参数,函数参数等。
" val"是指恒定的值。
" val"用于定义不可变字段或者变量或者属性。不可变字段表示一旦创建,便无法对其进行修改。
" var"表示不是恒定的变量。
" var"用于定义可变字段或者变量或者属性。可变字段表示我们创建后就可以对其进行修改。
Scala具有val和var的主要构造函数
在Scala中,我们可以使用val和var来定义Primary Constructor参数。
我们将通过简单的示例讨论每种情况,并观察一些Scala内部原理。
我们定义了三个不同的Scala源文件,如下所示:
示例1:-在Scala中,如果我们使用" var"定义主要构造函数的参数,则Scala编译器将为其生成setter和getter方法。
Person1.scala
class Person1(var firstName:String, var middleName:String, var lastName:String)
在"源文件"可用文件夹中打开命令提示符,并编译" Person1.scala",如下所示:
此步骤在同一文件夹中创建" Person1.class"文件。
" javap"命令是Java类文件反汇编程序。
使用此命令反汇编" Person1.class"以查看其内容,如下所示:
根据此输出,我们可以说" var"用于生成构造函数参数的setter和getter。
根据Scala表示法,firstName参数的setter和getter方法:
吸气法
public java.lang.String firstName();
设置方法
public void firstName_$eq(java.lang.String);
此" firstName_ $eq"方法名称等于" firstName_ ="。
当我们在标识符定义(类名,参数名,方法名等)中使用" ="时,它将由Scala编译器自动转换为" $eq"标识符。
注意:-Scala不遵循JavaBeans存取器和更改器方法的命名约定。
示例2:-在Scala中,如果我们使用" val"来定义Primary Constructor的参数,则Scala编译器将仅为其生成getter方法。
Person2.scala
class Person1(val firstName:String, val middleName:String, val lastName:String)
打开命令提示符,进行编译并使用" javap"进行反汇编以查看生成的Java代码,如下所示:
如果观察到此输出,则可以说" val"仅用于生成构造函数参数的getter。
按照Scala表示法,firstName,middleName和lastName参数的getter方法:
吸气方法
public java.lang.String firstName(); public java.lang.String middleName(); public java.lang.String lastName();
示例3:-在Scala中,如果我们不使用" var"和" val"来定义主要构造函数的参数,则Scala编译器不会为它们生成setter和getter方法。
Person3.scala
class Person1(firstName:String, middleName:String, lastName:String)
打开命令提示符,进行编译并使用" javap"进行反汇编以查看生成的Java代码,如下所示:
如果观察到此输出,则可以说没有为firstName,middleName和lastName构造函数参数生成setter和getter方法。
Scala主要构造函数简述
Scala主要构造函数包括以下内容:
- 构造函数参数在类定义中声明
- 在类主体中执行的所有语句和表达式
- 在类主体中调用的方法
- 在类主体中调用的字段
用简单的话来说,在类主体中定义的任何方法(方法声明除外)都是Scala主要构造函数的一部分。