Scala中的“类”和“对象”

82 阅读3分钟

在 Scala 中,类(class) 和 对象(object) 是面向对象编程的核心概念,但它们的用途和特性有所不同。下面详细介绍它们的区别与联系:

1. 类(class)

类是创建对象的模板,定义了对象的属性和行为。与 Java 中的类类似,但 Scala 的类更加简洁灵活。

基本特性:

  • 需要实例化:必须使用 new 关键字创建实例
  • 可带参数:类名后可直接定义参数(主构造函数)
  • 可被继承:默认不可被继承,需用 open 修饰(Scala 3)或加 extends 显式声明

示例:

// 带参数的类(主构造函数)
class Person(name: String, age: Int) {
  // 方法
  def introduce(): Unit = {
    println(s"I'm $name, $age years old")
  }
}

// 创建实例
val person = new Person("Alice", 30)
person.introduce()  // 输出: I'm Alice, 30 years old

2. 对象(object)

对象是 单例实例,无需实例化,自身就是一个实例。相当于 Java 中的单例模式,但语法更简洁。

基本特性:

  • 单例性:整个程序中只有一个实例
  • 无需 new:直接通过对象名访问
  • 不能带参数:对象定义不能有构造参数
  • 可作为工具类:常用于定义工具方法、常量等

示例:

object MathUtils {
  // 工具方法
  def add(a: Int, b: Int): Int = a + b
  def multiply(a: Int, b: Int): Int = a * b
}

// 直接使用,无需实例化
println(MathUtils.add(2, 3))       // 输出: 5
println(MathUtils.multiply(2, 3))  // 输出: 6

3. 伴生类与伴生对象

如果一个  和一个 对象 同名且定义在同一个文件中,它们互为 伴生类(class)  和 伴生对象(object)

特性:

  • 可以互相访问对方的私有成员
  • 伴生对象常作为类的工厂方法使用

示例:

// 伴生类
class Person private(val name: String) {  // 私有构造函数
  private def secret(): String = "I like Scala"
}

// 伴生对象
object Person {
  // 工厂方法(替代 new 创建实例)
  def apply(name: String): Person = new Person(name)
  
  // 访问伴生类的私有方法
  def getSecret(person: Person): String = person.secret()
}

// 使用伴生对象创建实例
val person = Person("Bob")  // 等价于 Person.apply("Bob")
println(Person.getSecret(person))  // 输出: I like Scala

4. 类与对象的核心区别

特性类(class)对象(object)
实例化需要用 new 创建实例无需实例化,自身就是实例
构造参数可以有参数(主 / 辅助构造)不能有参数
继承可被继承(需特殊修饰)不能被继承
用途定义实体模板单例、工具类、工厂方法

5. 应用场景

  • :用于定义实体(如 UserOrder),需要创建多个实例时使用

  • 对象

    • 工具类(如 DateUtils
    • 单例服务(如 Config
    • 伴生对象(为类提供工厂方法或访问私有成员)
    • 程序入口(object Main extends App { ... }
// 程序入口示例(对象作为主程序)
object Main extends App {
  println("Hello, Scala!")  // 直接运行,无需 main 方法
}

总结

  1. 类(class)

    • 是创建对象的模板,定义了对象的属性和行为
    • 需要通过 new 关键字实例化才能使用
    • 可包含构造参数(主构造函数)和辅助构造函数
    • 可被继承(Scala 3 中需用 open 修饰)
    • 主要用于定义需要多个实例的实体(如用户、订单等)
  2. 对象(object)

    • 是单例实例,自身就是唯一实例,无需 new 关键字
    • 不能定义构造参数
    • 不能被继承
    • 常用于工具类、单例服务、程序入口(extends App)等场景
  3. 特殊关系:伴生类与伴生对象

    • 同名且在同一文件中的类和对象互为伴生
    • 可互相访问对方的私有成员
    • 伴生对象常作为类的工厂方法,简化实例创建
  4. 核心差异

    • 类需要实例化,对象是单例无需实例化
    • 类可带构造参数,对象不能
    • 类可被继承,对象不能