[读书日志]从零开始学习Chisel 第三篇:Scala面向对象编程——类和对象(敏捷硬件开发语言Chisel与数字系统设计)

3.Scala面向对象编程

3.1类和对象
3.1.1类

类是用class开头的代码定义,定义完成后可以用new+类名的方式构造一个对象,对象的类型是这个类。类中定义的var和val类型变量称为字段,用def定义的函数称为方法。字段也称为实例变量,因为每个被构造出来的对象都有自己的字段,但所有的对象公用同样的方法。也就是说,定义一个类之后,每个对象的变量存储在独立的空间,互不相同;每个对象的方法是一样的,存储在同样的空间。使用new创建的对象可以赋值给一个变量,赋值给用val定义的变量,则这个变量之后不得被赋值给新的对象。代码如下:

scala> class Students {| var name = "None"| def register(n:String) = name = n| }
// defined class Students
​
scala> val stu = new Students
val stu: Students = Students@4fc454d5
​
scala> stu.name
val res29: String = None
​
scala> stu.register("Bob")
​
scala> stu.name
val res30: String = Bob
​
scala> stu.register("Jia")
​
scala> stu.name
val res31: String = Jia
​
scala> stu = new Students
-- [E052] Type Error: --------------------------------------------------------------------------------------------------
1 |stu = new Students|^^^^^^^^^^^^^^^^^^|Reassignment to val stu|| longer explanation available when compiling with `-explain`
1 error found

类的成员都是公共的,在 外部都可以被访问。如果不想被其他对象访问,可以在变量前加上private关键字。

3.1.2类的构造方法

主构造方法

Scala不同于C++,Python等语言,Scala没有专门的主构造语法,在类名后可以定义若干参数列表用于传递参数,参数会在初始化对象是传给类中的变量。类内部非字段,非方法的代码都被当做“主构造方法”。

scala> class Students(n:String) {| val name = n| println("A student named" + n + " has been registered.")| }
// defined class Students
​
scala> val stu = new Students("Tom")
A student namedTom has been registered.
val stu: Students = Students@33004de5

这里println既不是字段,也不是方法,所以被当成主构造函数的一部分。

辅助构造方法

在类的内部使用 def this(...)定义一个辅助构造方法,其第一步的行为必须是调用该类的另一个构造方法,即第一句必须是this(...)要么是主构造方法,要么是之前的另一个辅助构造方法。这种规则让任何构造方法最终都会调用类的主构造方法,使得主构造方法成为类的单一入口。

scala> class Students(n:String) {| val name = n| def this() = this("None")| println("A student named " + n + " has been registered.")| }
// defined class Students
​
scala> val stu = new Students
A student named None has been registered.
val stu: Students = Students@6f319f62
​
scala> val stu2c= new Students("Jia")
A student named Jia has been registered.
val stu2c: Students = Students@5a2e250b

这时存在两个构造函数,主构造函数需要传入一个String类型的量用于初始化,辅助析构函数不需要传入,因为它已经把这个量定义为了None。去掉这个析构函数,新创建对象时不传入String会导致报错:

scala> class Students(n:String) {|      val name = n|      println("A student named " + n + " has been registered.")|      }
// defined class Students
​
scala> val stu = new Students
-- [E171] Type Error: --------------------------------------------------------------------------------------------------
1 |val stu = new Students|          ^^^^^^^^^^^^|          missing argument for parameter n of constructor Students in class Students: (n: String): Students
1 error found

不能定义两个有歧义的辅助构造函数,这样写编译器无法确认在无参构造时究竟该调用哪一个构造函数:

scala> class Students(n:String) {| val name = n| def this() = this("None")| def this() = this("Jia")| println("A student named " + n + " has been registered.")| }
-- [E120] Naming Error: ------------------------------------------------------------------------------------------------
4 |def this() = this("Jia")|    ^|    Double definition:|    def <init>(): Students in class Students at line 3 and|    def <init>(): Students in class Students at line 4|    have the same type after erasure.||    Consider adding a @targetName annotation to one of the conflicting definitions|    for disambiguation.
1 error found

析构函数

Scala不需要定义析构函数。

私有主构造方法

在类的定义时加入private关键字,则主构造函数是私有的,外部无法调用主构造函数创建对象,只能使用其他公有的辅助构造方法或者工厂方法(专门用于构造对象的方法)

scala> class Students private (n:String,m:Int) {| val name = n| val score = m| def this(n:String) = this(n,100)| println(n + "'s score is" + m)| }
// defined class Students
​
scala> val stu = new Students("Bill",90)
-- [E007] Type Mismatch Error: -----------------------------------------------------------------------------------------
1 |val stu = new Students("Bill",90)|                       ^^^^^^^^^|                       Found:    (String, Int)|                       Required: String|| longer explanation available when compiling with `-explain`
1 error found
​
scala> val stu = new Students("Bill")
Bill's score is 100
val stu: Students = Students@45f675a4

主构造方法需要传入两个参数,但它是用private修饰的,所以外部无法调用。定义的辅助析构函数指定了第二个参数是100,只需要传入一个参数,因此外部可以调用这个辅助析构方法。

3.1.3重写toString方法

在构造一个Students类的对象时,Scala解释器打印了一串信息Students@45f675a4,这其实来自Students类的toString方法,这个方法返回一个字符串,构造完一个对象时被自动调用,这个方法是由所有Scala类隐式继承而来的,默认的toString方法将会简单地打印类名,一个“@”符号和一个十六进制数。如果向打印更多有用信息,可以自定义toString方法,但需要加上override关键字。

scala> class Students(n:String) {| val name = n| override def toString = "A student named " + n + "."| }
// defined class Students
​
scala> val stu = new Students("Jia")
val stu: Students = A student named Jia.
3.1.4方法重载

与C++类似,Scala支持方法重载,即在类内可以定义多个同名的方法,但参数(主要是参数类型)不一样,这个方法有很多不同版本,这称为方法重载。函数真正的特征是它的参数,而非函数名或返回类型。它与重写定义不同,重写是子类覆盖了超类的某个方法。

3.1.5类参数

Scala允许在类参数前加上val或var来修饰,这样可以在类的内部生成一个与参数同名的公有字段。还可以使用privateprotectedoverride来表面字段的权限。如果参数没有任何关键字,那么它就仅仅是参数,不是类的成员,只能用初始化字段赋值,内部无法修改,外部无法访问。(如前文中的参数,加上val也算加上了关键字,可以从外部访问,内部可以修改)

scala> class Students(val name: String, var score: Int) {| def exam(s:Int) = score = s| override def toString = name + "'s score is " + score + "."| }
// defined class Students
​
scala> val stu = new Students("Tim",90)
val stu: Students = Tim's score is 90.
​
scala> stu.exam(100)
​
scala> stu.score
val res32: Int = 100
3.1.6单例对象与伴生对象

除了使用new创建一个对象,也可以使用object,但它没有参数和构造方法,且数量只能有一个,因此被称为单例对象。如果某个单例对象和某个类同名,则称单例对象是这个类的伴生对象,这个类称为这个单例对象的伴生类。伴生类和伴生对象必须在同一个文件中,并且可以互相访问对方的所有成员。单例对象和类一样,也可以定义字段和方法,也可以包含别的类和单例对象的定义。单例对象也可以用于大宝某方面功能的函数系列成为一个工具集,或者包含主函数成为程序的入口。

object后面定义的单例对象名可以认为是这个单例对象的名称标签,因此可以通过据点符号访问单例对象的成员,也可以赋值给一个变量。

scala> object B {val b = "a singleton object"}
// defined object B
​
scala> B.b
val res33: String = a singleton object
​
scala> val x = B
val x: B.type = B$@3c4f0087
​
scala> x.b
val res34: String = a singleton object

定义一个类,就定义了一个类型;但定义单例对象并没有新产生一种类型,根本上来说,每个单例对象的类型都是object.type,伴生对象也没有定义类型,而是由伴生类定义的。但是,不同的object定义之间并不能互相赋值,它可以继承自超类或混入特质,因此定义的两个object对象并不是相同的类型:

scala> object X
// defined object X
​
scala> object Y
// defined object Y
​
scala> var x = X
var x: X.type = X$@304b2629
​
scala> x = Y
-- [E007] Type Mismatch Error: -----------------------------------------------------------------------------------------
1 |x = Y|    ^|    Found:    Y.type|    Required: X.type|| longer explanation available when compiling with `-explain`
1 error found
3.1.7工厂对象与工厂方法

如果定义一个专门用来构造某一个类的对象的方法,那么这种方法被称为工厂方法,包含这些工厂方法集合的单例对象,称为工厂对象。一般工厂对象会定义在伴生对象中,使用工厂方法的好处是可以不用直接使用new来实例化对象,改用方法调用,并且方法名是任意的,对外隐藏了类的实现细节。

首先我们创建一个students.scala的文件,在里面写入以下内容:

class Students(val name: String, var score: Int) {def exam(s:Int) = score = soverride def toString = name + "'s score is " + score + "."
}
​
object Students {def registerStu(name: String, score:Int) = new Students(name,score)
}

之后,编译这个文件:

jia@J-MateBookEGo:~/scala_test$ vim students.scala
jia@J-MateBookEGo:~/scala_test$ scalac students.scala

按照书上的方法,直接启动scala并使用import Students._导入会报错:

scala> import Students._
-- [E006] Not Found Error: ---------------------------------------------------------------------------------------------
1 |import Students._|       ^^^^^^^^|       Not found: Students|| longer explanation available when compiling with `-explain`
1 error found

这个时候我们需要添加class的路径,假设我们现在处于students.scala文件的路径下,经过编译会生成后缀是.class的文件,如果我们在这个文件的同路径下,使用这个代码导入class:

scala -classpath .

如果要添加其他路径的类,使用如下代码:

scala -classpath /path/to/classes

执行完这个指令后会直接进入scala解释器,使用如下代码调用:

scala> import Students._
​
scala> val stu = registerStu("Tim",100)
val stu: Students = Tim's score is 100.

其中,object定义的对象称为工厂对象,其中def定义的函数registerStu是工厂方法。

3.1.8 apply方法

apply方法是一个特殊名字的方法,如果定义了这个方法,可以显式调用 对象.apply(参数),也可以隐式调用 对象(参数),如果apply是无参方法,应该写出空括号。通常在伴生对象中定义名为apply的工厂方法,就能通过 伴生对象名(参数)来构造一个对象。也经常在类中定义一个与类相关,具有特定行为的apply方法。

我们在students2.scala中编写如下代码:

class Students2(val name:String, var score: Int) {def apply(s:Int) = score = sdef display() = println("Current core is " + score + ".")override def toString = name + "'s score is '" + score + "."
}
​
object Students2 {def apply(name: String, score: Int) = new Students2(name, score)
}

执行编译指令,并添加库路径:(这一步在之后不再赘述)

jia@J-MateBookEGo:~/scala_test$ vim students2.scala
jia@J-MateBookEGo:~/scala_test$ scalac students2.scala
jia@J-MateBookEGo:~/scala_test$ scala -classpath .

在解释器中执行如下代码:

scala> val stu2 = Students2("Jack",60)//隐式调用伴生对象中的工厂方法
val stu2: Students2 = Jack's score is 60.
​
scala> stu2(80)//隐式调用类的apply方法
​
scala> stu2.display()
Current core is 80.
3.1.9主函数

主函数是Scala程序的唯一入口,程序是从主程序开始执行的。要提供这样的入口,则必须在某个单例对象中定义一个名为main的函数,而且该函数只有一个参数,类型为字符串Array[String],函数的返回类型是Uint。任何符合条件的单例对象都能成为程序的入口。

编写一个main.scala文件,将其与之前编写的students2.scala一起编译:

//Start.scala
object Start {def main(args:Array[String]) = {try {val score = args(1).toIntval s = Students2(args(0), score)println(s.toString)} catch {case ex: ArrayIndexOutOfBoundsException => println("Arguments are deficient!")case ex: NumberFormatException => println("Second argument must be a Int!")}}
}

编译和执行指令:

jia@J-MateBookEGo:~/scala_test$ scala Start.scala students2.scala -- Tom
Arguments are deficient!
jia@J-MateBookEGo:~/scala_test$ scala Start.scala students2.scala -- Tom aaa
Second argument must be a Int!
jia@J-MateBookEGo:~/scala_test$ scala Start.scala students2.scala -- Tom 100
Tom's score is 100.

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

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

相关文章

Java SpringBoot使用Apache POI导入导出Excel文件

点击下载《Java SpringBoot使用Apache POI导入导出Excel文件(源代码)》 1. Apache POI 简介 Apache POI 是一个强大的 Java 库&#xff0c;用于处理 Microsoft Office 文档&#xff0c;包括 Excel 文件&#xff08;.xls 和 .xlsx&#xff09;。在 Java Spring Boot 项目中&am…

在 macOS 中,设置自动将文件夹排在最前

文章目录 1、第一步访达设置2、第二步排序方式 需要两步设置 1、第一步访达设置 按名称排序的窗口中 2、第二步排序方式 选择名称

汇编环境搭建

学习视频 将MASM所在目录 指定为C盘

Sentinel-5P遥感数据下载及预处理教程【20250105】

Sentinel-5P是欧空局&#xff08;Europe Space Agency&#xff0c;ESA&#xff09;于2017年10月13日发射的一颗全球大气污染监测卫星。卫星搭载了对流层观测仪&#xff08;Tropospheric Monitoring Instrument&#xff0c;TROPOMI&#xff09;&#xff0c;可以有效的观测全球各…

java项目之高校心理教育辅导系统的设计与实现(springboot+mybatis+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的闲一品交易平台。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 高校心理教育辅导系统的设…

打造三甲医院人工智能矩阵新引擎(一):文本大模型篇--基于GPT-4o的探索

一、引言 当今时代,人工智能技术正以前所未有的速度蓬勃发展,深刻且广泛地渗透至各个领域,医疗行业更是这场变革的前沿阵地。在人口老龄化加剧、慢性疾病患病率上升以及人们对健康需求日益增长的大背景下,三甲医院作为医疗体系的核心力量,承担着极为繁重且复杂的医疗任务。…

美的空气净化器好用吗?拾梧、美的、戴森空气净化器除烟哪个好?

说到二手烟&#xff0c;这可真是个让人头疼的问题&#xff01;它里面含有超过7000种化学物质&#xff0c;形式多样&#xff0c;处理起来比甲醛这些传统污染物难多了。在市场上那么多空气净化器里&#xff0c;要挑一个能真正对付二手烟的&#xff0c;简直就像大海捞针一样难。不…

WebRtc01:课程导学、框架介绍

应用 难点 课程大纲 学习收获 涉及内容 概述 用途 学习收获

电脑steam api dll缺失了怎么办?

电脑故障解析与自救指南&#xff1a;Steam API DLL缺失问题的全面解析 在软件开发与电脑维护的广阔天地里&#xff0c;我们时常会遇到各种各样的系统报错与文件问题&#xff0c;其中“Steam API DLL缺失”便是让不少游戏爱好者和游戏开发者头疼的难题之一。作为一名深耕软件开…

关系数据库查询与优化

关系数据库查询与优化 (1)查询所有没发表过文章的用户名(2)查询得票数大于100的所有文章标题,按得票数倒序排列(3)查询发表文章数大于5,文章平均得票数大于100的用户名,按平均得票数倒序排列(4)表的主键、外键和索引设计(5)大数据量下的存储及性能优化在关系数据库…

【Android项目学习】3. MVVMHabit

项目链接 文章目录 一. 项目结构1. 项目整体划分2. 模块细分 二. Android知识点学习1. registerActivityLifecycleCallbacks方法2. 一. 项目结构 1. 项目整体划分 MVVMHabit是以谷歌DataBindingLiveDataViewModel框架为基础&#xff0c;整合OkhttpRxJavaRetrofitGlide等流行…

GPU算力平台的应用之任意门:任意穿搭匹配模型的应用教程

大家好&#xff0c;今天给大家介绍一下&#xff1a;GPU算力平台的应用之任意门:任意穿搭匹配模型的应用教程。 文章目录 一、GPU算力平台概述人工智能智能发展为什么需要GPU算力平台 二、注册与登录账号注册流程 三、平台的应用之Anydoor应用启动器选择Anydoor的应用场景Anydoo…

学习虚幻C++开发日志——创建Selection Widget及其应用

教程视频&#xff1a;脚本冒险 - YouTube 前提&#xff1a;此代码运用到Common UI插件&#xff0c;需将其开启&#xff0c;以免后序编写产生未定义结构体的报错信息&#xff01; 用C进行UI绑定 创建继承于CommonUserWidget的类&#xff0c;此处命名为SelectionBase Select…

Kafka中的Topic和Partition有什么关系?

大家好&#xff0c;我是锋哥。今天分享关于【Kafka中的Topic和Partition有什么关系&#xff1f;】面试题。希望对大家有帮助&#xff1b; Kafka中的Topic和Partition有什么关系&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Apache Kafka 中&#…

SpringBoot Maven 项目 pom 中的 plugin 插件用法整理

把 SpringBoot Maven 项目打包成 jar 文件时&#xff0c;我们通常用到 spring-boot-maven-plugin 插件。 前面也介绍过&#xff0c;在 spring-boot-starter-parent POM 和 spring-boot-starter POM 中都有插件的管理&#xff0c;现在我们就撸一把构建元素中插件的用法。 一、…

c和c++中为什么要防止头文件被重复包含!

在编程中&#xff0c;头文件就像一本工具书&#xff0c;它包含了函数、类、宏、全局变量等的定义和声明&#xff0c;供其他代码文件引用。想象一下&#xff0c;如果你在写一篇文章时&#xff0c;反复引用同一本工具书的内容&#xff0c;会发生什么情况呢&#xff1f; 1. 避免重…

django vue3实现大文件分段续传(断点续传)

前端环境准备及目录结构&#xff1a; npm create vue 并取名为big-file-upload-fontend 通过 npm i 安装以下内容"dependencies": {"axios": "^1.7.9","element-plus": "^2.9.1","js-sha256": "^0.11.0&quo…

MCP(Model Context Protocol)模型上下文协议 进阶篇3 - 传输

MCP 目前定义了两种标准的客户端-服务端通信传输机制&#xff1a; stdio&#xff08;标准输入输出通信&#xff09;HTTP with Server-Sent Events (SSE)&#xff08;HTTP 服务端发送事件&#xff09; 客户端应尽可能支持 stdio。此外&#xff0c;客户端和服务端也可以以插件方…

openai swarm agent框架源码详解及应用案例实战

文章目录 简介数据类型Agent类Response类Result类Swarm类run_demo_loop交互式会话 基础应用agent-handsofffunction-callingcontext_variablestriage_agent 高阶应用通用客服机器人(support bot)构建航班服务agent 参考资料 openai 在24年10月份开源了一个教育性质的多agents协…

【顶刊TPAMI 2025】多头编码(MHE)之极限分类 Part 2:基础知识

目录 1 预热1.1 记号1.2 分类器计算过载问题 2 多头编码&#xff08;MHE&#xff09;2.1 标签分解2.2 多头组合&#xff08;Multi-Head Combination&#xff09; 论文&#xff1a;Multi-Head Encoding for Extreme Label Classification 作者&#xff1a;Daojun Liang, Haixia …