scala中的单例对象和伴生类

32 阅读2分钟

(一)单例对象

用 object 关键字来创建一个单例对象。单例对象在整个应用程序中只有一个实例,适合用于存放工具方法、常量或共享状态。

package t2

object test5 {
  //object对象名{
  //属性;
  //方法;
//}
//  单例对象
//  只有一个,不能被new;
//  适用于存放工具方法,常量

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

image.png

(二)伴生类和伴生对象

当同名的类和单例对象在同一个源码文件时,这个类称为单例对象的伴生类,对象称为类的伴生对象。

package t2

object test6 {
//  伴生类 和 伴生对象
//  1.类和对象同名
//  2.在一个文件中
//
//  类就是伴生类,对象就是伴生对象
//
//  特点:可以相互访问对方的私有成员

class Student(){
  //
  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)
  }
}

image.png

package t2

object test7 {
//  伴生类 和 伴生对象
//  1.类和对象同名
//  2.在一个文件中
//
//  类就是伴生类,对象就是伴生对象
//
//  特点:可以相互访问对方的私有成员

  //1.把构造器函数设置为private
class Student private() {

}
  //2.伴生对象中,访问private
object Student{
  //
  private val instance=new Student()

  def grtInstance():Student={
    instance
  }
  }

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

    println(stu1==stu2)
  }
  }

image.png

(一)apply的基本使用

在 Scala 中,apply 方法放在类的伴生对象(object)里,主要起到 工厂方法的作用,能够让使用者在创建该类实例时省去显式的 new 关键字,并且可以通过重载提供多种构造方式。

package t2

object test8 {
//  伴生类 和 伴生对象
//在伴生对象中补充一个apply方法,这样创建对象的时候,就可以省略new
//  伴生类名(参数)====伴生对象名.apply(参数)

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

}
  //2.伴生对象中,访问private
object Logger{
  def apply(filename:String):Logger= {
    println("apple...")
    new Logger(filename)
  }
  }


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

(二)apply实现单例模式

在上面的基础代码中,我们产生的对象还是在apply中通过new构造出来的,这样的话,如果我们多次生成对象,则得到的对象还是各不相同的。

package t2

object test8 {
  //  伴生类 和 伴生对象
  //在伴生对象中补充一个apply方法,这样创建对象的时候,就可以省略new
  //  伴生类名(参数)====伴生对象名.apply(参数)

  //日志
  class Logger(var filename: String) {
    def log(message: String): Unit = {
      println(s"log:$message")
    }

  }
  //2.伴生对象中,访问private


  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 = {
    val log1 = Logger("test.log")
    log1.log("2025-11-03 上午上课")
  }
}

image.png

(三)案例-日志类

package t2

import java.io.FileWriter

object test8 {
//  伴生类 和 伴生对象
//在伴生对象中补充一个apply方法,这样创建对象的时候,就可以省略new
//  伴生类名(参数)====伴生对象名.apply(参数)

  //日志
class Logger(var filename:String) {
    def log(message:String):Unit= {
      val writer=new FileWriter(filename,true)
      writer.write(s"$message \n")
      writer.close()
    }
}
  //2.伴生对象中,访问private


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 = {
  val log1=Logger("test.log")
  log1.log("2025-11-03 上午上课")
  log1.log("2025-11-05 开运动会")
  log1.log("2025-11-03 周末")
}
  }

image.png

image.png