Scala主要构造函数

时间:2020-02-23 14:41:48  来源:igfitidea点击:

在本文中,我们将通过实时场景示例深入讨论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主要构造函数的一部分。