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 对象的信息,并与模式中的名字、年龄和俱乐部进行匹配。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/679419.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Days28 ElfBoard 板]修改开机动画

1.可能需要安装的库 elfubuntu:~/work/psplash$ sudo apt-get install build-essential libncurses5-dev elfubuntu:~/work/psplash$ sudo apt-get install libtool elfubuntu:~/work/psplash$ sudo apt-get install gettext elfubuntu:~/work/psplash$ sudo apt-get install l…

熵与信息量简单理解。

一件事的信息量是啥东西?公式 -log2(P) P是这件事发生的概率 举例:a同学与b同学可以互相通信。双方约定用2进制传递信息。 1.例如:假定a能看到一个随机试验,就是从0-7中任意选一个数。这件事发生抽到了7。 a要把信息传递给b。…

Unity学习笔记(零基础到就业)|Chapter04:C#篇补充到Unity篇过渡

Unity学习笔记(零基础到就业)|Chapter02:C#篇补充到Unity篇过渡 前言C#总结补充1.值类型和引用类型有什么区别,他们在值的传递上分别有怎样的特性2.string是引用类型,但是他对外表现出值类型的特性,为什么&…

【AI大模型应用开发】【LangChain系列】6. LangChain的Callbacks模块:监控调试程序的重要手段

大家好,我是【同学小张】。持续学习,持续干货输出,关注我,跟我一起学AI大模型技能。 LangChain提供了一个回调系统,允许您挂接到LLM应用程序的各个阶段。这对于日志记录、监视、流式传输和其他任务非常有用。 0. Lang…

P1013 [NOIP1998 提高组] 进制位

P1013 [NOIP1998 提高组] 进制位 这破题我理解题解理解了三天……我是不是不适合学计算机 #include <iostream> #include <cstring> #include <unordered_map> // n <8 && n>2 (但是从0开始计数&#xff0c;故最大值是 1~7&#xff0c;最小值…

蓝桥杯每日一题之内存问题

蓝桥杯真题---内存问题 题目描述&#xff1a; 小蓝最近总喜欢计算自己的代码中定义的变量占用了多少内存空间。 为了简化问题&#xff0c;变量的类型只有以下三种&#xff1a; int&#xff1a;整型变量&#xff0c;一个 int 型变量占用 4 Byte 的内存空间。 long&#xff…

Mac中管理多版本Jdk

1. 首先下载JDK&#xff0c;以jdk8和17为例 2. 打开.zprofile中添加如下内容 #java config export JAVA_8_HOME/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home export JAVA_17_HOME/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home#default java …

如何在 Ubuntu 16.04 上设置 Jupyter Notebook 来运行 IPython

简介 IPython 是 Python 的交互式命令行界面。Jupyter Notebook 提供了一个交互式的 Web 界面&#xff0c;可以运行多种语言&#xff0c;包括 IPython。 本文将指导您设置一个服务器来运行 Jupyter Notebook&#xff0c;并教您如何连接和使用笔记本。Jupyter 笔记本&#xff…

【快速上手QT】02-学会查看QT自带的手册QT助手

QT助手 为什么大家都说QT简单&#xff0c;第一点就是确实简单&#xff08;bushi&#xff09;。 我个人觉得最关键的点就是人家QT官方就给你准备好了文档&#xff0c;甚至还有专门的IDE——QtCreator&#xff0c;在QTCreator里面还有很多示例代码&#xff0c;只要你会C的语法以…

Top 20 Docker 面试题(附答案)

Docker 是一种流行的开源软件平台&#xff0c;可简化创建、管理、运行和分发应用程序的过程。它使用容器来打包应用程序及其依赖项。Docker 主导了市场。大多数顶级云和 IT 公司都采用 Docker 来简化其应用程序开发工作流程。对具有 Docker 经验的申请人的需求很高。 破解 Doc…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Divider组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Divider组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Divider组件 提供分隔器组件&#xff0c;分隔不同内容块/内容元素。 子组件 …

C#使用重载方法实现不同类型数据的计算

目录 一、涉及到的相关知识 1.重载的方法 2.Convert.ToInt32(String)方法 3.判断字符串是否带有小数点 二、实例 1.示例 2.生成成果 一、涉及到的相关知识 1.重载的方法 重载方法就是方法名称相同&#xff0c;但是每个方法中参数的数据类型、个数或顺序不同的方法。如果…

【开源】JAVA+Vue.js实现高校学院网站

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 学院院系模块2.2 竞赛报名模块2.3 教育教学模块2.4 招生就业模块2.5 实时信息模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 学院院系表3.2.2 竞赛报名表3.2.3 教育教学表3.2.4 招生就业表3.2.5 实时信息表 四、系…

大语言模型不适合的范围

大语言模型在某些情况下可能不适用&#xff0c;主要体现在以下几个方面&#xff1a; 1、特定领域知识不足 大语言模型可能缺乏某些特定领域的专业知识&#xff0c;导致在特定行业或领域的问题上表现不佳。例如&#xff0c;在医学、法律等专业领域的术语和规范性语言理解方面可能…

收藏:《不要和不懂组织的人讨论管理》

刘润老师的文章&#xff1a;《不要和不懂组织的人讨论管理》&#xff0c;不错&#xff0c;收藏&#xff0c;地址&#xff1a;https://mp.weixin.qq.com/s?__bizMjM5NjM5MjQ4MQ&mid2651667396&idx1&snf98f294c19d1b6d6b608d013b4a39e32&chksmbd10608a8a67e99ce…

Vue-54、Vue技术vuex中四个map使用(mapState、mapGetters、mapActions、mapMutations)

1、mapState方法&#xff1a;用于帮助我们映射state中的数据为计算属性 computed:{//借助mapstate生成计算属性&#xff0c;从state中读取数据&#xff08;对象写法&#xff09;...mapState({sum:sum,school:school,subject:subject}),//借助mapstate生成计算属性&#xff0c;…

PyCharm2023.3.2配置conda环境

重点在于Path to conda这一步&#xff0c;需要找到conda.bat这个文件&#xff0c;PyCharm才能识别出现有的conda环境。

Spring Native 解放 JVM

一、Spring Native 是什么 Spring Native可以通过GraalVM将Spring应用程序编译成原生镜像&#xff0c;提供了一种新的方式来部署Spring应用。与Java虚拟机相比&#xff0c;原生镜像可以在许多场景下降低工作负载&#xff0c;包括微服务&#xff0c;函数式服务&#xff0c;非常…

第四节课[XTuner微调]作业

文章目录 前言作业基础作业-XTuner InternLM-Chat 个人小助手认知微调实践 前言 XTuner 做在第三节课LangChain作业之前&#xff0c;因为第三节课没想好找哪个领域&#xff0c;等第三节课作业做了一起部署。 作业 基础作业-XTuner InternLM-Chat 个人小助手认知微调实践 然…

数据采集接口分类:数据采集、数据的采集有哪些?

中国的人工智能会面临着前所未有的发展机遇&#xff0c;她也将会以真正解决人类钢需载入史册&#xff0c;我们也期待着在天津跟在座的各位合作伙伴共同努力&#xff0c;真正的用人工智能建设美好世界。 API接口数据采集 主流电商数据采集 一、 什么是数据采集 确立一个算法模…