8 scala的伴生对象

2024-02-12 15:04
文章标签 对象 scala 伴生

本文主要是介绍8 scala的伴生对象,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 单例对象

在编写 Java 程序时,我们经常会通过编写静态方法代码,去封装常用的 Utility 类。

在 Scala 中没有静态成员这一概念,所以,如果我们要定义静态属性或方法,就需要使用 Scala 的单例对象 object。Scala 的对象跟 Javascript 中定义一个对象,概念是差不多的。

下面定义一个球员对象,并在 main 函数打印球员对象的相关属性:

/*** 球员对象*/
object FootballPlayerObject {/*** 姓名*/var NAME: String = "Mohamed Salah"/*** 年纪*/var AGE: Int = 31/*** 所在俱乐部*/var CLUB: String = "Liverpool"/*** 定义入口 main 函数,打印球员对象相关属性* @param args*/def main(args: Array[String]): Unit = {System.out.println(FootballPlayerObject.NAME)System.out.println(FootballPlayerObject.AGE)System.out.println(FootballPlayerObject.CLUB)}
}

2 工具类案例

我们可以利用单例对象实现工具类,例如,下面实现了一个简易的 DateUtils

import org.joda.time.format.DateTimeFormat/*** 日期时间工具类*/
object DateUtils {val TIME_FORMAT = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")/*** 判断一个时间是否在另一个时间之前** @param time1 第一个时间* @param time2 第二个时间* @return 判断结果*/def before(time1: String, time2: String): Boolean = {TIME_FORMAT.parseDateTime(time1).isBefore(TIME_FORMAT.parseDateTime(time2))}/*** 判断一个时间是否在另一个时间之后** @param time1 第一个时间* @param time2 第二个时间* @return 判断结果*/def after(time1: String, time2: String): Boolean = {TIME_FORMAT.parseDateTime(time1).isAfter(TIME_FORMAT.parseDateTime(time2))}/*** 计算时间差值(单位为秒)** @param time1 时间1* @param time2 时间2* @return 差值*/def minus(time1: String, time2: String): Int = {((TIME_FORMAT.parseDateTime(time1).getMillis - TIME_FORMAT.parseDateTime(time2).getMillis) / 1000).toInt}def main(args: Array[String]): Unit = {println(DateUtils.before("2023-01-01 00:00:00", "2024-01-01 00:00:00"))println(DateUtils.after("2023-01-01 00:00:00", "2024-01-01 00:00:00"))println(DateUtils.minus("2024-01-01 00:00:00", "2023-01-01 00:00:00"))}
}

运行后,控制台打印:

true
false
31536000

3 伴生对象

如果想一个类,既需要静态成员,又需要实例成员,在 Scala 中可以使用伴生对象(companion object)来实现。

3.1 伴生对象的定义

伴生对象有以下特点:

(1) 伴生对象 和 类 必须要在同一个 class 文件中。

(2) 伴生对象名字要和类名字一致。

(3) 伴生类 和 伴生对象可以互相访问彼此的 private 属性。

/*** 球员信息类*/
class PlayerInfo(private var playerName: String, var age: Int, var club: String) {def hello(): String = {s"Hey buddy, I am ${this.playerName} of ${this.club}, ${this.age} years old!"}
}/*** PlayerInfo 类的共生对象*/
object PlayerInfo {/*** 定义球员梦想*/private var dream: String = "The dream of %s is achieving World Cup"/*** 打印球员梦想*/def myDream(playerName: String): String = {String.format(this.dream, playerName)}/*** main 方法* @param args*/def main(args: Array[String]): Unit = {// 定义球员信息对象val player: PlayerInfo = new PlayerInfo("Erling Haaland", 23, "Manchester City F.C.")println(player.hello())// 执行共生对象的 myDream 方法// 可以访问共生类的私有 playerNameprintln(this.myDream(player.playerName))}
}

3.2 apply 及 unapply 方法

在 Scala 中,applyunapply 是两个特殊的方法,它们通常与伴生对象一起使用,并且在模式匹配、构造对象等方面发挥着重要作用。

3.2.1 apply 方法

apply 方法通常用于对象的构造。当你调用类似 ClassName(args) 的代码时,实际上是调用了类的伴生对象的 apply 方法。这使得你可以像调用函数一样构造对象,而不需要显式地使用 new 关键字

例如,我们在定义一个列表时,并不需要使用 new: val list = List(1, 2, 3),下面为球员信息类的共生对象定义了 apply 方法:

/*** 球员信息类*/
class PlayerInfo(private var playerName: String, var age: Int, var club: String) {def hello(): String = {s"Hey buddy, I am ${this.playerName} of ${this.club}, ${this.age} years old!"}
}/*** PlayerInfo 类的共生对象*/
object PlayerInfo {/*** 定义球员梦想*/private var dream: String = "The dream of %s is achieving World Cup"/*** 打印球员梦想*/def myDream(playerName: String): String = {String.format(this.dream, playerName)}/*** 定义 apply 方法,新建一个 PlayerInfo 对象** @param playerName 球员名称* @param age 年龄* @return {@link PlayerInfo} 对象*/def apply(playerName: String, age: Int): PlayerInfo = new PlayerInfo(playerName, age, "Manchester City F.C.")/*** main 方法* @param args*/def main(args: Array[String]): Unit = {// 定义球员信息对象,有了 apply 方法后,不再需要 new 关键字val player: PlayerInfo = PlayerInfo("Erling Haaland", 23)println(player.hello())// 执行共生对象的 myDream 方法// 可以访问共生类的私有 playerNameprintln(this.myDream(player.playerName))}
}

3.2.2 unapply 方法

unapply 方法通常用于模式匹配。它是 Extractor 模式的一部分,允许你从对象中提取部分信息,并将其与模式进行匹配。

例如:

/*** 球员信息类*/
class PlayerInfo(private var playerName: String, var age: Int, var club: String) {def hello(): String = {s"Hey buddy, I am ${this.playerName} of ${this.club}, ${this.age} years old!"}
}/*** PlayerInfo 类的共生对象*/
object PlayerInfo {/*** 定义 apply 方法,新建一个 PlayerInfo 对象** @param playerName 球员名称* @param age 年龄* @return {@link PlayerInfo} 对象*/def apply(playerName: String, age: Int): PlayerInfo = new PlayerInfo(playerName, age, "Manchester City F.C.")/*** 定义 unapply,作为提取器,提取球员 姓名,年龄,俱乐部* @param playerInfo 球员信息对象* @return*/def unapply(playerInfo: PlayerInfo): Option[(String, Int, String)] = Some(playerInfo.playerName, playerInfo.age, playerInfo.club)/*** main 方法* @param args*/def main(args: Array[String]): Unit = {// 定义球员信息对象,有了 apply 方法后,不再需要 new 关键字val player: PlayerInfo = PlayerInfo("Erling Haaland", 23)player match {case PlayerInfo(name, age, club) => println(s"name: ${name}, age: ${age}, club: ${club}")case _ => println("Not matched")}}
}

在上面的代码中,unapply 方法从 PlayerInfo 对象中提取了名字、年龄和俱乐部,并将它们作为元组返回。在 match 表达式中,case PlayerInfo(name, age, club) 部分使用了模式匹配,它调用了 PlayerInfo 伴生对象的 unapply 方法来提取 PlayerInfo 对象的信息,并与模式中的名字、年龄和俱乐部进行匹配。

这篇关于8 scala的伴生对象的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/702835

相关文章

SpringMVC高效获取JavaBean对象指南

《SpringMVC高效获取JavaBean对象指南》SpringMVC通过数据绑定自动将请求参数映射到JavaBean,支持表单、URL及JSON数据,需用@ModelAttribute、@Requ... 目录Spring MVC 获取 JavaBean 对象指南核心机制:数据绑定实现步骤1. 定义 Ja

Python打印对象所有属性和值的方法小结

《Python打印对象所有属性和值的方法小结》在Python开发过程中,调试代码时经常需要查看对象的当前状态,也就是对象的所有属性和对应的值,然而,Python并没有像PHP的print_r那样直接提... 目录python中打印对象所有属性和值的方法实现步骤1. 使用vars()和pprint()2. 使

MySQL JSON 查询中的对象与数组技巧及查询示例

《MySQLJSON查询中的对象与数组技巧及查询示例》MySQL中JSON对象和JSON数组查询的详细介绍及带有WHERE条件的查询示例,本文给大家介绍的非常详细,mysqljson查询示例相关知... 目录jsON 对象查询1. JSON_CONTAINS2. JSON_EXTRACT3. JSON_TA

C#之List集合去重复对象的实现方法

《C#之List集合去重复对象的实现方法》:本文主要介绍C#之List集合去重复对象的实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C# List集合去重复对象方法1、测试数据2、测试数据3、知识点补充总结C# List集合去重复对象方法1、测试数据

Spring中管理bean对象的方式(专业级说明)

《Spring中管理bean对象的方式(专业级说明)》在Spring框架中,Bean的管理是核心功能,主要通过IoC(控制反转)容器实现,下面给大家介绍Spring中管理bean对象的方式,感兴趣的朋... 目录1.Bean的声明与注册1.1 基于XML配置1.2 基于注解(主流方式)1.3 基于Java

C++/类与对象/默认成员函数@构造函数的用法

《C++/类与对象/默认成员函数@构造函数的用法》:本文主要介绍C++/类与对象/默认成员函数@构造函数的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录名词概念默认成员函数构造函数概念函数特征显示构造函数隐式构造函数总结名词概念默认构造函数:不用传参就可以

C++类和对象之默认成员函数的使用解读

《C++类和对象之默认成员函数的使用解读》:本文主要介绍C++类和对象之默认成员函数的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、默认成员函数有哪些二、各默认成员函数详解默认构造函数析构函数拷贝构造函数拷贝赋值运算符三、默认成员函数的注意事项总结一

golang 对象池sync.Pool的实现

《golang对象池sync.Pool的实现》:本文主要介绍golang对象池sync.Pool的实现,用于缓存和复用临时对象,以减少内存分配和垃圾回收的压力,下面就来介绍一下,感兴趣的可以了解... 目录sync.Pool的用法原理sync.Pool 的使用示例sync.Pool 的使用场景注意sync.

SpringBoot项目中Redis存储Session对象序列化处理

《SpringBoot项目中Redis存储Session对象序列化处理》在SpringBoot项目中使用Redis存储Session时,对象的序列化和反序列化是关键步骤,下面我们就来讲讲如何在Spri... 目录一、为什么需要序列化处理二、Spring Boot 集成 Redis 存储 Session2.1

Java实例化对象的​7种方式详解

《Java实例化对象的​7种方式详解》在Java中,实例化对象的方式有多种,具体取决于场景需求和设计模式,本文整理了7种常用的方法,文中的示例代码讲解详细,有需要的可以了解下... 目录1. ​new 关键字(直接构造)​2. ​反射(Reflection)​​3. ​克隆(Clone)​​4. ​反序列化