【版权声明】博客内容由厦门大学数据库实验室拥有版权,未经允许,请勿转载!

[返回Spark教程首页]

类和对象是Java、C++等面向对象编程的基础概念。类是用来创建对象的蓝图。定义好类以后,就可以使用new关键字来创建对象。

简单的类

最简单的类的定义形式是:

class Counter{

//这里定义类的字段和方法

}

然后,就可以使用new关键字来生成对象:

new Counter //或者new Counter()

给类增加字段和方法

下面我们给这个类增加字段和方法:

class Counter {

private var value = 0

def increment(): Unit = { value += 1}

def current(): Int = {value}

}

在上面定义中,我们把value字段设置为private,这样它就成为私有字段,外界无法访问,只有在类内部可以访问该字段。如果字段前面什么修饰符都没有,就默认是public,外部可以访问该字段。对于类而言,我们并不需要声明为public,Scala文件中包含的多个类之间,都是彼此可见的。

对于方法的定义,是通过def实现的。上面的代码“def increment(): Unit = { value += 1}”中,increment()是方法,没有参数,冒号后面的Unit是表示返回值的类型,在Scala中不返回任何值,那么就用Unit表示,相当于Java中的void类型。方法的返回值,不需要靠return语句,方法里面的最后一个表达式的值就是方法的返回值,比如,上面current()方法里面只有一条语句“value”,那么,value的值就是该方法的返回值。

因为increment()方法只是对value的值进行了增加1的操作,并没有返回任何值,所以,返回值类型是Unit。Unit后面的等号和大括号后面,包含了该方法要执行的具体操作语句。如果大括号里面只有一行语句,那么也可以直接去掉大括号,写成下面的形式:

class Counter {

private var value = 0

def increment(): Unit = value += 1 //去掉了大括号

def current(): Int = {value} //作为对比,这里依然保留大括号

}

或者,还可以去掉返回值类型和等号,只保留大括号,如下:

class Counter {

private var value = 0

def increment() {value += 1} //去掉了返回值类型和等号,只保留大括号

def current(): Int = {value} //作为对比,这里依然保留原来形式

}

创建对象

下面我们新建对象,并调用其中的方法:

val myCounter = new Counter

myCounter.increment() //或者也可以不用圆括号,写成myCounter.increment

println(myCounter.current)

从上面代码可以看出,Scala在调用无参方法时,是可以省略方法名后面的圆括号的。

编译和执行

现在,让我们把上面完整的代码拿到Linux系统中执行。请在登录Linux系统后,打开命令行终端(可以使用快捷组合键Ctr+Alt+T,快速打开命令行终端),进入到“/usr/local/scala/mycode”目录下,然后使用vim编辑器新建一个TestCounter.scala代码文件,如下:

cd /usr/local/scala/mycode

vim TestCounter.scala

在TestCounter.scala中输入以下代码:

class Counter {

private var value = 0

def increment(): Unit = { value += 1}

def current(): Int = {value}

}

val myCounter = new Counter

myCounter.increment()

println(myCounter.current)

保存后退出vim编辑器。然后,使用scala命令执行这个代码文件:

scala TestCounter.scala

上面命令执行后,会在屏幕输出“1”。

这是在Linux的Shell命令中执行。实际上,我们也可以进入到Scala解释器下面去执行,首先启动Scala解释器,如下:

scala //在终端窗口中输入scala命令进入Scala解释器

这时就进入了scala命令提示符状态,可以在里面输入如下命令:

scala> :load /usr/local/scala/mycode/TestCounter.scala //这是输入的命令

Loading /usr/local/scala/mycode/TestCounter.scala... //从这里开始是执行结果

defined class Counter

myCounter: Counter = Counter@17550481

1

完成上面操作以后,我们可以退出Scala解释器,回到Linux系统的Shell命令提示符状态,退出Scala解释器的命令如下:

scala> :quit

下面,我们尝试一下,看看是否可以使用scalac命令对这个TestCounter.scala文件进行编译,如下:

scalac TestCounter.scala

执行上述scalac命令后,你会发现,会出现一堆错误,无法编译。为什么呢?因为,当我们使用scalac命令对TestCounter.scala进行编译时,必须要求把声明(比如val myCounter = new Counter以及myCounter.increment()等)都封装在对象中,这也是JVM字节码的要求。但是,在TestCounter.scala中,这些声明都没有被封装在对象中,所以,无法编译。

不过,如果我们确实需要把TestCounter.scala编译为JVM字节码,那么,可以使用下面命令:

scalac -Xscript Upper1 TestCounter.scala //编译

scala -classpath . Upper1 //执行

执行后会在屏幕上返回结果:1。在上面代码中,-Xscript后面跟着的名称Upper1是你自己定义的main类名称,你愿意起个名字叫Upper2,也是可以的。

好了,还记得我们在前面给大家介绍的HelloWorld程序吗?当时用的是一个包含了main()方法的大家比较熟悉的JVM应用程序,这种方式是本教程中推荐使用的方式,现在,我们采用这种方式重新编写上面的代码。

请在Linux系统的Shell命令提示符状态下,进入到“/usr/local/scala/mycode”目录下,然后使用vim编辑器新建一个TestCounterJVM.scala代码文件,如下:

cd /usr/local/scala/mycode

vim TestCounterJVM.scala

在TestCounterJVM.scala中输入以下代码:

class Counter {

private var value = 0

def increment(): Unit = { value += 1}

def current(): Int = {value}

}

object MyCounter{

def main(args:Array[String]){

val myCounter = new Counter

myCounter.increment()

println(myCounter.current)

}

}

保存后退出vim编辑器。然后,使用scalac命令编译这个代码文件,并用scala命令执行,如下:

scalac TestCounterJVM.scala

scala -classpath . MyCounter //MyCounter是包含main方法的对象名称,这里不能使用文件名称TestCounterJVM

上面命令执行后,会在屏幕输出“1”。

现在我们对之前的类定义继续改进一下,让方法中带有参数。我们可以修改一下TestCounterJVM.scala文件:

class Counter {

private var value = 0

def increment(step: Int): Unit = { value += step}

def current(): Int = {value}

}

object MyCounter{

def main(args:Array[String]){

val myCounter = new Counter

myCounter.increment(5) //这里设置步长为5,每次增加5

println(myCounter.current)

}

}

采用上面介绍的方法,编译执行这个文件,就可以得到执行结果是5。

getter和setter方法

下面我们来看一下如何给类中的字段设置值以及读取值。我们知道,在Java中,这是通过getter和setter方法实现的。在Scala中,也提供了getter和setter方法的实现,但是并没有定义成getXxx和setXxx。

我们继续修改TestCounterJVM.scala文件:

class Counter {

var value = 0 //注意这里没有private修饰符,从而让这个变量对外部可见

def increment(step: Int): Unit = { value += step}

def current(): Int = {value}

}

object MyCounter{

def main(args:Array[String]){

val myCounter = new Counter

println(myCounter.value) //不是用getXxx获取字段的值

myCounter.value = 3 //不是用setXxx设置字段的值

myCounter.increment(1) //这里设置步长为1,每次增加1

println(myCounter.current)

}

}

编译执行这个文件,就可以得到两行执行结果,第一行是0,第二行是4。

但是,我们都知道,在Java中,是不提倡设置这种公有(public)字段的,一般都是把value字段设置为private,然后提供getter和setter方法来获取和设置字段的值。那么,到了Scala中该怎么做呢?

我们先把value字段声明为private,看看会出现什么效果,继续修改TestCounterJVM.scala文件:

class Counter {

private var value = 0 //增加了private修饰符,成为私有字段

def increment(step: Int): Unit = { value += step}

def current(): Int = {value}

}

object MyCounter{

def main(args:Array[String]){

val myCounter = new Counter

println(myCounter.value) //不是用getXxx获取字段的值

myCounter.value = 3 //不是用setXxx设置字段的值

myCounter.increment(1) //这里设置步长为1,每次增加1

println(myCounter.current)

}

}

现在我们去用scalac命令编译上面的代码,就会报错,会出现“error:variable value in class Counter cannot be accessed in Counter”这样的错误信息。因为,value字段前面用了修饰符private,已经成为私有字段,外部是无法访问的。

那么,value变成私有字段以后,Scala又没有提供getter和setter方法,怎么可以访问value字段呢?解决方案是,在Scala中,可以通过定义类似getter和setter的方法,分别叫做value和value_=,具体如下:

class Counter {

private var privateValue = 0 //变成私有字段,并且修改字段名称

def value = privateValue //定义一个方法,方法的名称就是原来我们想要的字段的名称

def value_=(newValue: Int){

if (newValue > 0) privateValue = newValue //只有提供的新值是正数,才允许修改

}

def increment(step: Int): Unit = { value += step}

def current(): Int = {value}

}

object MyCounter{

def main(args:Array[String]){

val myCounter = new Counter

println(myCounter.value) //打印value的初始值

myCounter.value = 3 //为value设置新的值

println(myCounter.value) //打印value的新值

myCounter.increment(1) //这里设置步长为1,每次增加1

println(myCounter.current)

}

}

编译执行这个文件,就可以得到三行执行结果,第一行是0,第二行是3,第三行是4。

辅助构造器

Scala构造器包含1个主构造器和若干个(0个或多个)辅助构造器。

我们首先认识一下辅助构造器。辅助构造器的名称为this,每个辅助构造器都必须调用一个此前已经定义的辅助构造器或主构造器。

下面定义一个带有辅助构造器的类,我们对上面的Counter类定义进行修改:

class Counter {

private var value = 0 //value用来存储计数器的起始值

private var name = "" //表示计数器的名称

private var mode = 1 //mode用来表示计数器类型(比如,1表示步数计数器,2表示时间计数器)

def this(name: String){ //第一个辅助构造器

this() //调用主构造器

this.name = name

}

def this (name: String, mode: Int){ //第二个辅助构造器

this(name) //调用前一个辅助构造器

this.mode = mode

}

def increment(step: Int): Unit = { value += step}

def current(): Int = {value}

def info(): Unit = {printf("Name:%s and mode is %d\n",name,mode)}

}

object MyCounter{

def main(args:Array[String]){

val myCounter1 = new Counter //主构造器

val myCounter2 = new Counter("Runner") //第一个辅助构造器,计数器的名称设置为Runner,用来计算跑步步数

val myCounter3 = new Counter("Timer",2) //第二个辅助构造器,计数器的名称设置为Timer,用来计算秒数

myCounter1.info //显示计数器信息

myCounter1.increment(1) //设置步长

printf("Current Value is: %d\n",myCounter1.current) //显示计数器当前值

myCounter2.info //显示计数器信息

myCounter2.increment(2) //设置步长

printf("Current Value is: %d\n",myCounter2.current) //显示计数器当前值

myCounter3.info //显示计数器信息

myCounter3.increment(3) //设置步长

printf("Current Value is: %d\n",myCounter3.current) //显示计数器当前值

}

}

编译执行上述代码后,得到如下结果:

Name: and mode is 1

Current Value is: 1

Name:Runner and mode is 1

Current Value is: 2

Name:Timer and mode is 2

Current Value is: 3

主构造器

Scala的每个类都有主构造器。但是,Scala的主构造器和Java有着明显的不同,Scala的主构造器是整个类体,需要在类名称后面罗列出构造器所需的所有参数,这些参数被编译成字段,字段的值就是创建对象时传入的参数的值。

对于上面给计数器设置name和mode的例子,刚才我们是使用辅助构造器来对name和mode的值进行设置,现在我们重新来一次,这次我们转而采用主构造器来设置name和mode的值。

class Counter(val name: String, val mode: Int) {

private var value = 0 //value用来存储计数器的起始值

def increment(step: Int): Unit = { value += step}

def current(): Int = {value}

def info(): Unit = {printf("Name:%s and mode is %d\n",name,mode)}

}

object MyCounter{

def main(args:Array[String]){

val myCounter = new Counter("Timer",2)

myCounter.info //显示计数器信息

myCounter.increment(1) //设置步长

printf("Current Value is: %d\n",myCounter.current) //显示计数器当前值

}

}

编译执行上述代码后,得到如下结果:

Name:Timer and mode is 2

Current Value is: 1

scala的mysql类封装_Scala入门:类相关推荐

  1. 3-1:类与对象入门——类的引入和类的定义以及访问限定符和封装还有对面向对象的理解

    文章目录 一:面向对象与面向过程 二:类的引入 三:类的定义 (1)C++类的定义 (2)类的两种定义方式 A:声明和定义全部放在类体中 B:定义和声明分开放 四:类的访问限定符及封装 (1)访问限定 ...

  2. c++.net 托管类封装非托管类

    C++.net中非托管的代码虽然在托管里面可以直接使用,但是有时候却会被限制.比如当需要用托管里面的 ArrayList 存储一个非托管的对象的时候就需要用一个托管的类把这个非托管的类封装一下,其他的 ...

  3. 封装一个新闻类News,包含新闻标题,新闻作者,新闻内容,新闻类型三个属性,提供必要的访问器和修改器方法重写toString方法,要求打印对象时输出格式为“标题;

    封装一个新闻类News,包含新闻标题,新闻作者,新闻内容, 新闻类型三个属性,提供必要的访问器和修改器方法,重写toString方法, 要求打印对象时输出格式为"标题:类型:作者" ...

  4. MySQL数据库学习笔记(十一)----DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)...

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  5. java mysql jdbc 封装_利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包括增删改查、JavaBean反射原理,附源代码)...

    近期看老罗的视频,跟着完毕了利用Java操作MySql数据库的一个框架类JdbcUtils.java,完毕对数据库的增删改查.当中查询这块,包含普通的查询和利用反射完毕的查询,主要包含以下几个函数接口 ...

  6. spring入门(11)-spring与hibernate整合完成增删改查的操作(封装HibernateTemplate模版类对象)

    今天是spring的最后一节课,这节课老师讲了spring与hibernate整合完成增删改查的操作,这是很重要的一节课,这也是第一次真正的实现spring结合Hibernate和数据库连接上,下面是 ...

  7. scala案例_Scala案例类和案例对象深入(第1部分)

    scala案例 发表简短目录 (Post Brief TOC) Introduction介绍 What is Case Class什么是案例类 What is Case Object什么是案例对象 S ...

  8. scala案例_Scala案例类和案例对象深入(第2部分)

    scala案例 发表简短目录 (Post Brief TOC) Introduction介绍 Scala's Case Class Benefit-6Scala案例类权益6 Advantages of ...

  9. java jdbc工具类抽取_JavaWeb入门(三):JDBC工具类的抽取

    一.通过上篇文章,我们已经可以使用JDBC对数据库中的表进行增删改查啦(JDBC的基本使用:https://www.cnblogs.com/Infancy/p/12499806.html),我们对上篇 ...

最新文章

  1. 吴恩达演讲直指AI落地三大挑战,并提出解决方案
  2. banana pi BPI-R1 原理图下载地址:
  3. 全球及中国管道运输行业建设发展与投资战略规划报告2022版
  4. 打印show attend and tell的解码器网络结构
  5. 那些年,我的数据结构课设,现在满满的回忆!(现如今身处内卷之中,已经很难出现当初那份乐趣了)
  6. dylib java_将dylib库嵌入macOS应用的方法
  7. C#编程高并发的几种处理方法
  8. android zxing-3.3.3的用法_Android使用RecyclerView实现复杂的多布局效果
  9. html 弹窗 支持ie8,浏览器兼容性的问题、支持IE8、不支持IE6、想解决这个问题、两个都支持、...
  10. Spring Boot 2.x 把 Guava 干掉了,拥抱本地缓存之王 Caffeine!
  11. ​ 最大尺寸的超宽高刷新率显示器 —— Legion Y44w 上手体验
  12. C++:Socket:WSAStartup和WSADATA
  13. 小薛读论文04:预测、解决方案与滚动时域 (UTD24期刊MSOM重要综述)
  14. 如何将pdf在线翻译成英文?
  15. D. Nastia Plays with a Tree(树形dp)
  16. 【工程/物理光学(二)——几何光学基础与光的成像】
  17. ubuntu20.04如何录制屏幕
  18. C++中definition与declaration的区别
  19. 手机品牌,型号,分辨率,系统,版本号
  20. 自己造个真正意义上的AI纸片人离我们还有多远?

热门文章

  1. win7 SQL Server2014安装
  2. 会唱歌的棒棒糖3D展示效果,产品三维模型运用
  3. Win11 win10系统分区时出现defrag事件怎么解决?
  4. php .asmx,php实现soap调用.Net的WebService asmx文件
  5. 酷玩机:如何使笔记本在计算机盖合上后仍继续工作
  6. 从零开始自制实现WebServer(十六)---- 学习新工具CMake自动编写MakeFile 分门别类整理源文件心情愉悦
  7. SQL 查询最新套餐用户
  8. 概念:Roc, AUC, Precision, Recall
  9. 苹果手机黑屏了,怎么办?
  10. 纯干货:微软漏洞中国第一人黄正——如何用正确姿势挖掘浏览器漏洞(附完整 PPT)|硬创公开课...