位置:首页 > Scala > Scala 类入门:主构造器、字段可变性与方法定义一次看懂

Scala 类入门:主构造器、字段可变性与方法定义一次看懂

时间:2026-08-23  |  作者:电竞小硕  |  阅读:0

Classes

为了支持面向对象编程,Scala提供了类结构,相比于Ja va和C#等语言,它的语法更为简洁, 但他仍然是易用且可读的.

Basic Class Constructors

创建一个简单的类,并定义一个有两个参数的类构造器, 代码示例如下:

class Person(var firstName: String, var lastName: String)

// Use Class Person 
val person = new Person("Andrew", "Li")
println(person.firstName + " " + person.lastName)   // Andrew Li

在Scala类构造器中定义的所有参数,都会在编译期间自动在类中创建出对应的变量,如示例可见,构造器定义了两个var变量,因此他们都是可修改的,修改方式见如下代码示例:

person.firstName = "Shuai"

println(person.firstName + " " + person.lastName)   // Shuai Li

我们对比下在Scala和Ja va中创建一个简单类的区别,看看Scala的类是否足够简洁,代码示例如下:

// Create a class in Scala
class Person(var firstName: String, var lastName: String)
// Create a class in Ja va
public class Person {

    private String firstName;
    private String lastName;
    
    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    
    public String getFirstName() {
        return this.firstName;
    }
    
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    
    public String getLastName() {
        return this.lastName;
    }
    
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    
}

val makes fileds read-only

前边提到,Person类中所有的字段都被定义成var, 这些字段是可变的.实际上你也可以将这些字段定义成val,这样所有的字段将是不可变的, 如下代码示例所见:

class Person(val firstName: String, val lastName: String)

// Use Person class
val person = new Person("Andrew", "Li")
person.firstName = "Shuai"    // error: reassignment to val

小贴士:在使用Scala进行面向对象编程时,使用var来定义class的变量会更合适些,因为这样能随意对其进行修改。 然而,当使用Scala进行函数式编程时,通常我们会使用case class,而非class。case class适用于不可变的数据,函数式编程中提倡数据不可变,因为不可变能够确保程序的健壮性。

Class Structure

在Scala中, class主要有以下几个组成部分:

  • class构造器的参数

  • 类主体中定义的被调用的方法

  • 类主体中能够在初始化(new)时被直接执行的语句和表达式

当然了,除了构造器中的变量,你可以在class中定义一些变量, 跟Ja va极其相似,这些变量将会在class初始化时被分配指定的值.

如下代码示例展示了你能在class中进行的一些操作:

class Person(var firstName: String, var lastName: String) {

  println("the constructor begins")

  // 'public' access by default
  var age = 0

  // some class fields
  private val AMOUNT_OF_EYES = 2

  // some methods
  override def toString(): String = s"$firstName $lastName is $age years old"

  def printAmountOfEyes(): Unit = println(s"AMOUNT_OF_EYES = $AMOUNT_OF_EYES")

  def printDescription(): Unit = println(this)

  printAmountOfEyes()
  printDescription()
  println("you've reached the end of the constructor")
}
var person = new Person("Andrew", "Li")

// When executing the above code to init person object, we can see those logs as follows:

// the constructor begins
// AMOUNT_OF_EYES = 2
// Andrew Li is 0 years old
// you've reached the end of the constructor

Auxiliary Class Constructors

我们可以通过定义this方法来定义"补充类构造器", 在定义补充类构造器时需要注意一下几点:

  • 每个补充类构造器必须有不同的方法签名(在这里主要是不同类构造器的的参数必须不同)
  • 每个补充类构造器必须调用一个之前已经定义好的构造器

代码示例如下:

// the primary constructor
class Person (var name: String, var age: Int) {

  // one-arg auxiliary constructor
  def this(age: Int) = {
    this("default name", age)
  }

  // one-arg auxiliary constructor
  def this(name: String) = {
    this(name, 0)
  }

  // zero-arg auxiliary constructor
  def this() = {
    this("default name", 0)
  }

  override def toString = s"The person called $name is $age years old"

}

Tip:

  • 补充类构造器是一个好的特性,但是因为Scala中我们可以给参数指定默认值,因此实际上补充类构造器使用的场景并不多, 在下一节中我们将学习如何给参数指定默认值.

Supplying Default Values for Constructor Parameters

Scala支持我们给类构造器指定默认值, 代码示例如下:

class Socket(var timeout: Int = 2000, var linger: Int = 3000) {
  override def toString = s"timeout: $timeout, linger: $linger"
}

我们可以通过如下示例中的几种方式创建Socket对象:

new Socket()
new Socket(1000)
new Socket(4000, 6000)

Benefits:

  • 你可以提供首选的, 默认的值为你的类构造器参数
  • 这将允许使用你定义的类的开发者根据他们自己的要求覆盖那些默认值

Bonus: Named parameters

Scala还有一个有用的特性,当你在创建类实例的时候可以你可以使用命名的参数,见如下代码示例:

val socket = new Socket(linger=3000, timeout=2000)

val socket = new Socket(timeout=2000)
val socket = new Socket(linger=3000)

很明显,如上的示例将比如下示例更具可读性:

val socket = new Socket(2000, 3000)

Basic Scala Methods

在Scala中, 方法是被定义在类里的, 接下来我们将看一下常见的用法, 见如下代码示例:

def double(a: Int) = a * a

// Explicitly declare the return value
def double(a: Int): Int = a * a

我们可以自由决定方法的返回值类型是否显式声明。若函数体逻辑简单,返回值类型容易判断,可不显式声明。但如果返回值类型是自定义类型,且方法体逻辑复杂,难以直接看出返回值,那么显式声明返回值类型就很有必要,这能极大提升代码的可读性。

方法的结构说明:

  • def 是声明方法的关键字
  • double 是方法的名称,尽量用业务含义为方法命名
  • a: Int 是方法的参数, a是参数名, Int 是参数类型
  • : Int 是显式声明了方法的返回值类型
  • a * a 是方法体,单行方法体可以用直接用 = 定义,如上述代码示例, 多行方法体需要使用{}定义,代码示例如下:
def addThenDouble(a: Int, b: Int): Int = {
  val sum = a + b
  val doubled = sum * 2
  doubled
}

创作不易,希望大家多多支持,文章每周持续更新,我们下期见.

从零卷到嗯 | [原创]

点关注不迷路

大家有任何问题都可以通过微信公众号来联系我,知无不言~

wechat.png

《夸克》非常好用的免费AI浏览器

下载APP查看

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多