scala的单例对象和伴生类

34 阅读1分钟

单例对象

用 object 关键字来创建一个单例对象。单例对象在整个应用程序中只有一个实例,不能被new

适合用于存放工具方法、常量或共享状态。

格式

屏幕截图 2025-11-03 091715.png

object class05 {
  
  object MyTool {
    // 属性
    val PI = 3.14
    // 方法
    def Area(r:Double):Double ={
      PI * r * r
    }
  }
  def main(args: Array[String]): Unit = {

    //对象.属性名
    //对象.方法名

    println(MyTool.PI)  // 3.14
    println(MyTool.Area(10)) // 314.0
    
  }
}

伴生类和伴生对象

类就是伴生类,对象就是伴生对象

类和对象同名且在一个文件中

Scala的伴生对象和伴生类的特点:伴生对象和类的私有private成员可以相互访问。

object class06 {

  class Student() {
    // private 修饰的属性,无法在类的外部被访问
    private val hobby = "打游戏"
  }

  object Student {
    def introduce(stu:Student): Unit = {
      println(s"我的爱好是:${stu.hobby}")
    }
  }
  def main(args: Array[String]): Unit = {
    val stu1 = new Student()
    // stu1.hobby  // 无法访问私有属性

    Student.introduce(stu1)
  }
}

单例模式

单例模式:伴生类和伴生对象,实现一种特殊的编程的模式

让一个类只能有一个实例对象,一个类只能被new一次!

object class07 {

  // 1.把构造函数设置为private
    class Student private() {
    }
    
  // 2.伴生对象中,访问private
  object Student {
    private val instance = new Student() //在伴生对象中可以访问private修饰的构造器

    def getInstance(): Student = {
      instance
    }
  }

  def main(args: Array[String]): Unit = {
  
    // 无法通过 new 来创建对象!
    // val stu1 = new Student()
    // val stu2 = new Student()
    // println(stu1 == stu2) // false
    
    val stu1 = Student.getInstance()
    val stu2 = Student.getInstance()
    println(stu1 == stu2)    // true
  }
}

apply方法

在伴生对象中补充一个apply方法,这样创建对象的时候,就可以省略 new

伴生类名(参数) ==== 伴生对象名.apply(参数)

object class08 {
// Logger:日志类
  class Logger(var filename:String) {

  }
  object Logger {
    def apply(filename:String):Logger = {
      println("apply...")
      new Logger(filename)
    }
  }
  def main(args: Array[String]): Unit = {
    // 省略 new
    val log1 = Logger("test.log")
    println(log1.filename) //test.log
  }
}

伴生类和伴生对象+apply 实现单例模式

案例:日志类

object class08 {
  class Logger(var filename:String) {

    def log(message:String):Unit = {
      println(s"Log:$message")
    }
  }

  object Logger {
    private var instance:Option[Logger] = None
    def apply(filename:String):Logger = {
      if(instance.isEmpty) {
        instance = Some(new Logger(filename))
      }
      instance.get
    }
  }
  def main(args: Array[String]): Unit = {
    // 省略 new
    val log1 = Logger("test.log")
    log1.log("2025-11-03 上午上课") // Log:2025-11-03 上午上课
  }
}

目标:把日志信息写入到文件中

import java.io.FileWriter // 自动重新

object class08 {
  class Logger(var filename:String) {
    def log(message:String):Unit = {
    
      // 把日志信息写入到文件中
      val writer = new FileWriter(filename,true)
      writer.write(s"$message \n")
      writer.close()
    }
  }

  object Logger {
    private var instance:Option[Logger] = None
    def apply(filename:String):Logger = {
      if(instance.isEmpty) {
        instance = Some(new Logger(filename))
      }
      instance.get
    }
  }
  def main(args: Array[String]): Unit = {

    log1.log("2025-11-03 上午上课")
    log1.log("2025-11-05 开运动会")
    log1.log("2025-11-07 周末")
  }
}

运行结果如下:

屏幕截图 2025-11-03 113040.png