scala_单例对象、apply方法

本文介绍了Scala中的单例对象,包括如何定义单例对象、在单例对象中定义成员方法以及工具类案例。此外,还详细讲解了伴生对象的概念,如何定义伴生对象、private[this]访问权限以及伴生对象的apply方法。通过示例展示了如何在实践中使用这些概念,如定义main方法和实现App Trait作为程序入口。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单例对象

scala中没有Java中的静态成员,我们想要定义类似于Java的static变量、static方法,就要使用到scala中的单例对象——object.

定义单例对象

单例对象表示全局仅有一个对象(类似于Java static概念)

  • 定义单例对象和定义类很像,就是把class换成object
  • 在object中定义的成员变量类似于Java的静态变量
  • 可以使用object直接引用成员变量

示例

示例说明

  • 定义一个Dog单例对象,保存狗有几条腿
  • 在main方法中打印狗腿的数量

参考代码

object _08ObjectDemo {

  // 定义一个单例对象
  object Dog {
    // 定义腿的数量
    val LEG_NUM = 4
  }

  def main(args: Array[String]): Unit = {
    println(Dog.LEG_NUM)
  }
}

在单例对象中定义成员方法

  • 在object中定义的成员方法类似于Java的静态方法

示例

示例说明

  • 设计一个单例对象,定义一个能够打印分割线(15个减号)的方法
  • 在main方法调用该方法,打印分割线

参考代码

object _09ObjectDemo {

  object PrintUtil {

    // 打印分割线
    def printSpliter() = {
      // 字符串乘法,表示返回多少个字符串
      println("-" * 10)
    }
  }

  def main(args: Array[String]): Unit = {
    PrintUtil.printSpliter()
  }
}

工具类案例

需求

  • 编写一个DateUtil工具类专门用来格式化日期时间
  • 定义一个方法,用于将日期(Date)转换为年月日字符串,例如:2030-10-05

步骤

  • 定义一个DateUtil单例对象,定义日期格式化方法(format)
  • 使用SimpleDateFormat将日期转换为字符串

参考代码

object _10ObjectDemo {

  object DateUtils {
    // 在object中定义的成员变量,相当于Java中定义一个静态变量
    // 定义一个SimpleDateFormat日期时间格式化对象
    val simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm")

    // 相当于Java中定义一个静态方法
    def format(date: Date) = simpleDateFormat.format(date)
  }

  // main是一个静态方法,所以必须要写在object中
  def main(args: Array[String]): Unit = {
    println(DateUtils.format(new Date()))
  }
}

伴生对象

在Java中,经常会有一些类,同时有实例成员又有静态成员。例如:

public class CustomerService {

    private static String SERVICE_NAME = "CustomerService";

    public void save() {
        // 保存客户
        System.out.println(SERVICE_NAME + ":保存客户");
    }

    public static void main(String[] args) {
        new CustomerService().save();
    }
}

在scala中,要实现类似的效果,可以使用伴生对象来实现。


我们还可以使用伴生对象来实现快速创建对象,例如:

// 无需使用new就可以快速来创建对象
val a = Array(1,2,3)
val b = Set(1,2,3)

定义伴生对象

一个class和object具有同样的名字。这个object称为伴生对象,这个class称为伴生类

  • 伴生对象必须要和伴生类一样的名字
  • 伴生对象和伴生类在同一个scala源文件中
  • 伴生对象和伴生类可以互相访问private属性

示例

示例说明

  • 编写一个CustomerService类,有一个save方法,打印

    服务类名称:保存客户
    
  • 编写一个CustomerService伴生对象,定义一个私有变量,用于保存服务类名称

  • 创建CustomerService对象,调用save方法

参考代码

object _11ObjectDemo {

  class CustomerService {
    def save() = {
      println(s"${CustomerService.SERVICE_NAME}:保存客户")
    }
  }

  // CustomerService的伴生对象
  object CustomerService {
    private val SERVICE_NAME = "CustomerService"
  }

  def main(args: Array[String]): Unit = {
    val customerService = new CustomerService()
    customerService.save()
  }
}

private[this]访问权限

如果某个成员的权限设置为private[this],表示只能在当前类中访问。伴生对象也不可以访问

示例

示例说明

  • 定义一个Person类,包含一个name字段
  • 定义Person类的伴生对象,定义printPerson方法
  • 测试伴生对象是否能访问private[this]权限的成员

示例代码

  class Person(private[this] var name:String)
  
  object Person {
    def printPerson(person:Person): Unit = {
      println(person.name)
    }
  }
  
  def main(args: Array[String]): Unit = {
    val person = new Person("张三")
    Person.printPerson(person)
  }

上述代码,会编译报错。但移除掉[this]就可以访问了

main方法

scala和Java一样,如果要运行一个程序,必须有一个main方法。而在Java中main方法是静态的,而在scala中没有静态方法。在scala中,这个main方法必须放在一个单例对象中。

定义main方法

main方法

def main(args:Array[String]):Unit = {
    // 方法体
}

示例

示例说明

  • 创建一个单例对象,在该单例对象中打印"hello, scala"

参考代码

object Main5 {
  def main(args:Array[String]) = {
    println("hello, scala")
  }
}

实现App Trait来定义入口

创建一个object,继承自App Trait(特质),然后将需要编写在main方法中的代码,写在object的构造方法体内。

object 单例对象名 extends App {
    // 方法体
}

示例

示例说明

  • 继承App特质,来实现一个入口。同样输出"hello, scala"

参考代码

object Main5 extends App {
  println("hello, scala")
}

伴生对象 | apply方法

我们之前使用过这种方式来创建一个Array对象。

// 创建一个Array对象
val a = Array(1,2,3,4)

这种写法非常简便,不需要再写一个new,然后敲一个空格,再写类名。我们可以通过伴生对象的apply方法来实现。

定义

定义apply方法

object 伴生对象名 {
	def apply(参数名:参数类型, 参数名:参数类型...) = new 类(...)
}

创建对象

伴生对象名(参数1, 参数2...)

示例

示例说明

  • 定义一个Person类,它包含两个字段:姓名和年龄
  • 重写apply方法,使用Person类名就可以创建对象
  • 在main方法中创建该类的对象,并打印姓名和年龄

参考代码

object _12ApplyDemo {
  class Person(var name:String = "", var age:Int = 0)

  object Person {
    // 定义apply方法,接收两个参数
    def apply(name:String, age:Int) = new Person(name, age)
  }

  def main(args: Array[String]): Unit = {
    // 使用伴生对象名称来创建对象
    val zhangsan = Person("张三", 20)
    println(zhangsan.name)
    println(zhangsan.age)
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值