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 中,apply 和 unapply 是两个特殊的方法,它们通常与伴生对象一起使用,并且在模式匹配、构造对象等方面发挥着重要作用。
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的伴生对象
1 单例对象 在编写 Java 程序时,我们经常会通过编写静态方法代码,去封装常用的 Utility 类。 在 Scala 中没有静态成员这一概念,所以,如果我们要定义静态属性或方法,就需要使用 Scala 的单例对象 object。Scala 的对…...
Redis相关介绍
概念 Redis:非关系型数据库(non-relational),Mysql是关系型数据库(RDBMS) Redis是当今非常流行的基于KV结构的作为Cache使用的NoSQL数据库 为什么使用NoSQL 关系型 数据库无法应对每秒上万次 的读写请求 表中的存储记录 数量有限 无法简单…...
Transformer实战-系列教程13:DETR 算法解读
🚩🚩🚩Transformer实战-系列教程总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 点我下载源码 1、物体检测 说到目标检测你能想到什么 faster-rcnn系列,开山之作&…...
代码随想录刷题笔记 DAY 25 | 组合问题 No.77 | 组合求和III No.216 | 电话号码的字母组合 No.17
文章目录 Day 2501. 组合问题(No. 77)2.1 题目2.2 笔记2.3 代码 02. 组合求和III(No. 216)2.1 题目2.2 笔记2.3 代码 03. 电话号码的字母组合(No. 17)3.1 题目3.2 笔记3.3 代码3.4 补充 Day 25 01. 组合问…...
upload-labs文件上传漏洞靶场
第一关 <?php eval ($_POST[123]);?>发现他这个是通过客户端前端写了一个限制 我们禁用srcipt即可 蚁剑成功打开 第二关 我们上传文件2.php它提示我们文件类型不正确 我们可以联想到做了后缀检测 我们通过burp抓包修改后缀 第三关 我们上传一个.php文件不可上…...
企业计算机服务器中了mkp勒索病毒怎么办?Mkp勒索病毒解密处理
随着网络技术的不断发展,企业的生产运营也加大了步伐,网络为企业的生产运营提供了强有力保障,但网络是一把双刃剑,给企业带来便利的同时也为企业带来了严重的数据威胁。春节期间,云天数据恢复中心接到很多企业的值班人…...
STM32-寄存器和HAL库以及如何使用
在电子工程领域,“寄存库”和“HAL库”都是与微控制器(MCU)编程紧密相关的概念。 寄存器(Register) 含义: 在电子工程领域,特别是计算机体系结构和微控制器设计中,寄存器是一种非常…...
手动下载spacy的en_core_web_sm模型
手动下载 首先,用下面连接下载模型。我下载了 .tar.gz 格式。 然后提取它并通过指定所需子文件夹的路径将其加载到代码中。为了确保路径正确,您应该进入包含 config.cfg 文件的文件夹。 https://github.com/explosion/spacy-models/releases 例子代码…...
Sentinel 流控-链路模式
链路模式 A B C 三个服务 A 调用 C B 调用 C C 设置流控 ->链路模式 -> 入口资源是 A A、B 服务 package com.learning.springcloud.order.controller;import com.learning.springcloud.order.service.BaseService; import org.springframework.beans.factory.annotatio…...
Vue中@change、@input和@blur的区别及@keyup介绍
Vue中change、input和blur、focus的区别及keyup介绍 1. change、input、blur、focus事件2. keyup事件3. 补充:el-input的change事件自定义传参 1. change、input、blur、focus事件 change在输入框发生变化且失去焦点后触发; input在输入框内容发生变化后…...
洛谷: P7910 [CSP-J 2021] 插入排序
题目链接:P7910 [CSP-J 2021] 插入排序 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路: 1.定义结构体,将输入数据和它是第几位绑定起来。增加一个数组f[x],记录原来序列中的第x个在新序列中的位置,每执行一次修改操作,我们…...
Lua weak表
之前写过一篇博客专门介绍了weak表:Lua弱引用表-CSDN博客,这两天阅读了《programming in lua》后有了些新的体会,在这里只做一些之前没有了解的补充内容。 定义 Lua 自动进行内存的管理。程序只能创建对象(表,函数等…...
DS:二叉树的顺序结构及堆的实现
创作不易,兄弟们给个三连!! 一、二叉树的顺序存储 顺序结构指的是利用数组来存储,一般只适用于表示完全二叉树,原因如上图,存储不完全二叉树会造成空间上的浪费,有的人又会问,为什么…...
python从入门到精通(十九):python的多线程详细使用
python的多线程详细使用 1.什么是线程2.线程的作用3.导入线程4.创建线程启动线程线程阻塞线程的方法守护线程线程阻塞2个都是守护线程1个是守护线程线程间通信1.什么是线程 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指…...
【More Effective C++】条款19:了解临时对象的来源
临时对象:没有命名,不会出现在源代码中 帮助隐式类型转换成功而创建的对象 编译器创建一个类型为string的临时对象,以buffer作为参数,调用string的构造函数;str绑定到了这个临时对象上函数返回时,这个临时…...
站在C/C++的肩膀速通Java面向对象
默认学过C或C,对变量、表达式、选择、循环都会。 运行特征 解释型语言(JavaScript、Python等) 源文件-(平台专属解释器)->解释器中执行编译型语言(C、Go等) 源文件-(平台编译器)->平台可执行文件Java 源文件-(…...
【AI视野·今日Robot 机器人论文速览 第七十八期】Wed, 17 Jan 2024
AI视野今日CS.Robotics 机器人学论文速览 Wed, 17 Jan 2024 Totally 49 papers 👉上期速览✈更多精彩请移步主页 Daily Robotics Papers Safe Mission-Level Path Planning for Exploration of Lunar Shadowed Regions by a Solar-Powered Rover Authors Olivier L…...
flask cors 跨域问题解决
座右铭:怎么简单怎么来,以实现功能为主。 欢迎大家关注公众号与我交流 环境安装 pip install -U flask-cors 示例代码 from flask import Flask from flask_cors import CORS, cross_originapp Flask(__name__) CORS(app, supports_credentialsTrue)…...
18 19 SPI接口的74HC595驱动数码管实验
1. 串行移位寄存器原理(以四个移位寄存器为例) 1. 通过移位寄存器实现串转并:一个数据输入端口可得到四位并行数据。 通过给data输送0101数据,那么在经过四个时钟周期后,与data相连的四个寄存器的输出端口得到了0101…...
计算机网络概述习题拾遗
学习目标: 自下而上第一个提供端到端服务的层次 路由器、交换机、集线器实现的功能层 TCP/IP体系结构的网络接口层对应OSI体系结构的哪两个层次 分组数量对总时延的影响 如果这篇文章对您有帮助,麻烦点赞关注支持一下动力猿吧! 学习内容…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...
嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...
UE5 音效系统
一.音效管理 音乐一般都是WAV,创建一个背景音乐类SoudClass,一个音效类SoundClass。所有的音乐都分为这两个类。再创建一个总音乐类,将上述两个作为它的子类。 接着我们创建一个音乐混合类SoundMix,将上述三个类翻入其中,通过它管理每个音乐…...
GB/T 43887-2024 核级柔性石墨板材检测
核级柔性石墨板材是指以可膨胀石墨为原料、未经改性和增强、用于核工业的核级柔性石墨板材。 GB/T 43887-2024核级柔性石墨板材检测检测指标: 测试项目 测试标准 外观 GB/T 43887 尺寸偏差 GB/T 43887 化学成分 GB/T 43887 密度偏差 GB/T 43887 拉伸强度…...
